**xloops** was written to implement the methods developed in Mainz for
calculating one- and two-loop Feynman diagrams. Whereas many other packages
for loop calculations are often ad-hoc implementations computing numeric
results for very specific processes or special cases (but quite efficiently
so), the idea of **xloops** is to have a program that works for arbitrary
massive diagrams to any tensor rank, and that can also return analytic
results if possible. Eventually, **xloops** will be expanded into a
package for the complete automatic calculation of processes in the Standard
Model.

The roots of **xloops** go back to a Maple package for one-loop integrals
released in 1993. Due to inherent problems with Maple as an implementation
environment, the project was switched to C++ in 1999. One result of this was
the creation of **GiNaC**, a C++ library for symbolic computation, that
is now a project of its own.

Currently, **xloops** consists of a library of C++ and GiNaC functions
for calculating arbitrary one-loop one-, two-, and three-point, and two-loop
self-energy integrals of any tensor rank. All one-loop integrals and the
divergent part of two-loop integrals are returned in symbolic form as an
expansion in the dimensional regularization parameter ε. The finite
part of two-loop integrals is transformed into a two-dimensional function
that is numerically integrable.

**A one-loop calculation**

Here is a complete example program that calculates the divergent and finite parts of the general rank-1 one-loop two-point integral:#include <iostream> #include <ginac/ginac.h> #include <xloops/xloops.h> using std::cout; using std::endl; using namespace GiNaC; using namespace xloops; int main(void) { // Declare symbols for momentum, masses, and parameters symbol q("q"), m1("m1"), m2("m2"), eps("eps"), rho("rho"); // One-loop integral function ex C = OneLoop2Pt(1, 0, q, m1, m2, 1, 1, rho, eps); // Perform epsilon-expansion C = C.series(eps == 0, 1); // Extract the divergent and finite parts ex div = C.coeff(eps, -1).subs(rho == 0).normal(); ex fin = C.coeff(eps, 0).subs(rho == 0); // Output the result cout << "Order eps^-1 is " << endl << div << endl; cout << "Order eps^0 is " << endl << fin << endl; return 0; }

**A two-loop calculation**

The following program first computes the divergent part of the scalar two-loop sunrise topology. Then it evaluates the finite part of the integral for a specific choice of the masses and the external momentum.#include <iostream> #include <ginac/ginac.h> #include <xloops/xloops.h> using std::cout; using std::endl; using namespace GiNaC; using namespace xloops; int main(void) { // Declare symbols for momentum, masses, and parameters symbol q("q"); symbol m1("m1"), m2("m2"), m3("m3"); symbol rho("rho"), eps("eps"); symbol x("x"), y("y"); // Two-loop two-point integral function, sunrise topology ex C = TwoLoop2Pt4(0, 0, 0, 0, 0, q, lst(m1, m2, m3), lst(1, 1, 1), rho, eps, lst(x, y)); // The result is a two-element list containing the analytic and numeric // parts; extract them ex num = C.op(0); ex ana = C.op(1); // Perform epsilon-expansion of the analytic part ana = ana.series(eps == 0, 1); // Extract the divergent (eps^-2 and eps^-1) and finite parts ex eps2 = collect_common_factors(ana.coeff(eps, -2).subs(rho == 0).normal()); ex eps1 = collect_common_factors(ana.coeff(eps, -1).subs(rho == 0).normal()); ex eps0 = ana.coeff(eps, 0); // Output the result for the divergent part cout << "eps^-2 = " << eps2 << endl; cout << "eps^-1 = " << eps1 << endl; // Substitute values for masses and momentum in the finite parts lst s; s = rho == 1E-15, m1 == 2, m2 == 4, m3 == 6, m4 == 8, m5 == 10, q == 20; eps0 = eps0.subs(s).evalf(); fin = fin.subs(s); // Perform numerical integration using Vegas fin = VNumInt(fin, 10000, 10, 100000, 10, lst(x, y)); // Output the result for the finite part, including the finite // analytic term cout << "finite = " << fin.op(0) + fin.op(2)*I + eps0 << endl; cout << "error real part = " << fin.op(1) << endl; cout << "error imag part = " << fin.op(3) << endl; return 0; }