diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a3af55174..a55e819f7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,12 +23,9 @@ jobs: - {bin: tform, test: default} - {bin: tform, test: default, nthreads: 2} - {bin: parform, test: default, timeout: 15} - - {bin: form, test: checkpoint} - - {bin: tform, test: checkpoint} - - {bin: form, test: forcer, timeout: 60} - - {bin: tform, test: forcer, timeout: 60} - - {bin: tform, test: forcer, nthreads: 2, timeout: 60} - - {bin: tform, test: multithreaded} + - {bin: form, test: extra, timeout: 60} + - {bin: tform, test: extra, timeout: 60} + - {bin: tform, test: extra, nthreads: 2, timeout: 60} steps: - name: Checkout repository uses: actions/checkout@v4 @@ -69,7 +66,7 @@ jobs: - name: Cache library id: cache-formlib - if: contains(fromJson('["forcer"]'), matrix.test) + if: contains(fromJson('["extra"]'), matrix.test) uses: actions/cache@v4 with: path: formlib @@ -80,11 +77,14 @@ jobs: run: | mkdir -p formlib case ${{ matrix.test }} in - forcer) + extra) + # forcer library for the forcer test in extra wget https://github.com/benruijl/forcer/archive/v1.0.0.tar.gz -O - | tar -x --gzip mv forcer-1.0.0/forcer.h formlib mv forcer-1.0.0/forcer formlib rm -rf forcer-1.0.0 + # color library for the color test in extra + wget https://www.nikhef.nl/~form/maindir/packages/color/color.h -P formlib ;; esac @@ -97,37 +97,40 @@ jobs: # thoroughly by using Valgrind on Linux. To maximize the use of concurrent # jobs, we divide the tests into smaller parts. valgrind-check: - name: Valgrind check for ${{ matrix.bin }}${{ matrix.nthreads && format(' -w{0}', matrix.nthreads) || '' }} (${{ matrix.group }}) + name: Valgrind check (${{ matrix.test }}) for ${{ matrix.bin }}${{ matrix.nthreads && format(' -w{0}', matrix.nthreads) || '' }} (${{ matrix.group }}) runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: include: - - {bin: vorm, group: 1/5} - - {bin: vorm, group: 2/5} - - {bin: vorm, group: 3/5} - - {bin: vorm, group: 4/5} - - {bin: vorm, group: 5/5} - - {bin: tvorm, group: 1/10} - - {bin: tvorm, group: 2/10} - - {bin: tvorm, group: 3/10} - - {bin: tvorm, group: 4/10} - - {bin: tvorm, group: 5/10} - - {bin: tvorm, group: 6/10} - - {bin: tvorm, group: 7/10} - - {bin: tvorm, group: 8/10} - - {bin: tvorm, group: 9/10} - - {bin: tvorm, group: 10/10} - - {bin: tvorm, nthreads: 2, group: 1/10} - - {bin: tvorm, nthreads: 2, group: 2/10} - - {bin: tvorm, nthreads: 2, group: 3/10} - - {bin: tvorm, nthreads: 2, group: 4/10} - - {bin: tvorm, nthreads: 2, group: 5/10} - - {bin: tvorm, nthreads: 2, group: 6/10} - - {bin: tvorm, nthreads: 2, group: 7/10} - - {bin: tvorm, nthreads: 2, group: 8/10} - - {bin: tvorm, nthreads: 2, group: 9/10} - - {bin: tvorm, nthreads: 2, group: 10/10} + - {bin: vorm, test: default, group: 1/5} + - {bin: vorm, test: default, group: 2/5} + - {bin: vorm, test: default, group: 3/5} + - {bin: vorm, test: default, group: 4/5} + - {bin: vorm, test: default, group: 5/5} + - {bin: tvorm, test: default, group: 1/10} + - {bin: tvorm, test: default, group: 2/10} + - {bin: tvorm, test: default, group: 3/10} + - {bin: tvorm, test: default, group: 4/10} + - {bin: tvorm, test: default, group: 5/10} + - {bin: tvorm, test: default, group: 6/10} + - {bin: tvorm, test: default, group: 7/10} + - {bin: tvorm, test: default, group: 8/10} + - {bin: tvorm, test: default, group: 9/10} + - {bin: tvorm, test: default, group: 10/10} + - {bin: tvorm, test: default, nthreads: 2, group: 1/10} + - {bin: tvorm, test: default, nthreads: 2, group: 2/10} + - {bin: tvorm, test: default, nthreads: 2, group: 3/10} + - {bin: tvorm, test: default, nthreads: 2, group: 4/10} + - {bin: tvorm, test: default, nthreads: 2, group: 5/10} + - {bin: tvorm, test: default, nthreads: 2, group: 6/10} + - {bin: tvorm, test: default, nthreads: 2, group: 7/10} + - {bin: tvorm, test: default, nthreads: 2, group: 8/10} + - {bin: tvorm, test: default, nthreads: 2, group: 9/10} + - {bin: tvorm, test: default, nthreads: 2, group: 10/10} + - {bin: vorm, test: extra, group: 1/1} + - {bin: tvorm, test: extra, group: 1/1} + - {bin: tvorm, test: extra, nthreads: 2, group: 1/1} steps: - name: Checkout repository uses: actions/checkout@v4 @@ -159,21 +162,50 @@ jobs: - name: Build run: make -C sources -j 4 ${{ matrix.bin }} + - name: Cache library + id: cache-formlib + if: contains(fromJson('["extra"]'), matrix.test) + uses: actions/cache@v4 + with: + path: formlib + key: formlib-${{ matrix.test }} + + - name: Install library if necessary + if: steps.cache-formlib.outputs.cache-hit != 'true' + run: | + mkdir -p formlib + case ${{ matrix.test }} in + extra) + # forcer library for the forcer test in extra + wget https://github.com/benruijl/forcer/archive/v1.0.0.tar.gz -O - | tar -x --gzip + mv forcer-1.0.0/forcer.h formlib + mv forcer-1.0.0/forcer formlib + rm -rf forcer-1.0.0 + # color library for the color test in extra + wget https://www.nikhef.nl/~form/maindir/packages/color/color.h -P formlib + ;; + esac + - name: Test - run: ./check/check.rb valgrind ./sources/${{ matrix.bin }} --stat -g ${{ matrix.group }} --retries 5 ${{ matrix.nthreads && format('-w{0}', matrix.nthreads) || '' }} + run: ./check/check.rb valgrind ./sources/${{ matrix.bin }} --stat -g ${{ matrix.group }} --retries 5 ${{ matrix.nthreads && format('-w{0}', matrix.nthreads) || '' }} ${{ matrix.test != 'default' && format('-C {0}', matrix.test) || '' }} + env: + FORMPATH: ${{ github.workspace }}/formlib # Generate LCOV coverage data to be posted to coveralls.io. Note that # we measure code coverage only for tests checked with Valgrind. coverage: - name: Code coverage for ${{ matrix.bin }}${{ matrix.nthreads && format(' -w{0}', matrix.nthreads) || '' }} + name: Code coverage (${{ matrix.test }}) for ${{ matrix.bin }}${{ matrix.nthreads && format(' -w{0}', matrix.nthreads) || '' }} runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: include: - - {bin: vorm} - - {bin: tvorm} - - {bin: tvorm, nthreads: 2} + - {bin: vorm, test: default} + - {bin: tvorm, test: default} + - {bin: tvorm, test: default, nthreads: 2} + - {bin: vorm, test: extra, timeout: 60} + - {bin: tvorm, test: extra, timeout: 60} + - {bin: tvorm, test: extra, nthreads: 2, timeout: 60} steps: - name: Checkout repository uses: actions/checkout@v4 @@ -202,8 +234,34 @@ jobs: - name: Build run: make -C sources -j 4 ${{ matrix.bin }} + - name: Cache library + id: cache-formlib + if: contains(fromJson('["extra"]'), matrix.test) + uses: actions/cache@v4 + with: + path: formlib + key: formlib-${{ matrix.test }} + + - name: Install library if necessary + if: steps.cache-formlib.outputs.cache-hit != 'true' + run: | + mkdir -p formlib + case ${{ matrix.test }} in + extra) + # forcer library for the forcer test in extra + wget https://github.com/benruijl/forcer/archive/v1.0.0.tar.gz -O - | tar -x --gzip + mv forcer-1.0.0/forcer.h formlib + mv forcer-1.0.0/forcer formlib + rm -rf forcer-1.0.0 + # color library for the color test in extra + wget https://www.nikhef.nl/~form/maindir/packages/color/color.h -P formlib + ;; + esac + - name: Test - run: ./check/check.rb ./sources/${{ matrix.bin }} --stat --timeout 30 ${{ matrix.nthreads && format('-w{0}', matrix.nthreads) || '' }} --fake-valgrind + run: ./check/check.rb ./sources/${{ matrix.bin }} --stat --timeout ${{ matrix.timeout && format('--timeout {0}', matrix.timeout) || '30' }} ${{ matrix.nthreads && format('-w{0}', matrix.nthreads) || '' }} ${{ matrix.test != 'default' && format('-C {0}', matrix.test) || '' }} --fake-valgrind + env: + FORMPATH: ${{ github.workspace }}/formlib - name: Generate LCOV coverage data run: | @@ -213,7 +271,7 @@ jobs: - name: Coveralls Parallel uses: coverallsapp/github-action@v2 with: - flag-name: ${{ matrix.bin }}${{ matrix.nthreads && format(' -w{0}', matrix.nthreads) || '' }} + flag-name: ${{ matrix.bin }}${{ matrix.nthreads && format(' -w{0}', matrix.nthreads) || '' }} (${{ matrix.test }}) parallel: true # Post LCOV coverage data to coveralls.io. diff --git a/check/Makefile.am b/check/Makefile.am index 6178d8053..7a277a92f 100644 --- a/check/Makefile.am +++ b/check/Makefile.am @@ -30,9 +30,12 @@ EXTRA_DIST = \ benchmark-fu.sh \ check-help.sh \ check.rb \ - checkpoint/checkpoint.frm \ examples.frm \ + extra/checkpoint.frm \ + extra/color.frm \ + extra/forcer.frm \ + extra/multithreaded.frm \ features.frm \ fixes.frm \ - forcer/forcer.frm \ - formunit/fu.frm + formunit/fu.frm \ + user.frm diff --git a/check/checkpoint/checkpoint.frm b/check/extra/checkpoint.frm similarity index 100% rename from check/checkpoint/checkpoint.frm rename to check/extra/checkpoint.frm diff --git a/check/extra/color.frm b/check/extra/color.frm new file mode 100644 index 000000000..1c18f2728 --- /dev/null +++ b/check/extra/color.frm @@ -0,0 +1,165 @@ +#ifndef `TEST' + #message Use -D TEST=XXX + #terminate +#else + #include `NAME_' # `TEST' +#endif +.end + +*--#[ color_tloop : +#- + +* This is a modified version of tloop.frm from the color.h example files. + +Off Statistics; + +* Larger than 5 becomes extremely slow under valgrind. +#define SIZE "5" +*#define ALTERNATEMETHOD "1" +* +* Test program for the color traces in the paper and a few more. +* The paper: "Color traces for arbitrary groups" +* by T. van Ritbergen, A.N. Schellekens and J.A.M. Vermaseren. +* +* The object is to express color traces in terms of group invariants +* in such a way that the group has not been specified yet. The few +* remaining invariants can be substituted afterwards. The expressions +* in terms of invariants are better for publications. One sees more +* about the structure of the problem this way. +* +* All declarations are made in the file cfactors.h +* One needs version 3 or later of FORM to run these programs. +* The programs will handle all color structures with up to 14 vertices. +* One vertex is one generator in any representation. +* Currently the program handles only one type of non-adjoint representaion. +* If there are two different representations of such type one has to +* try to run the problem in stages. +* +* Examples are: +* One quark-loop with SIZE gluons in a maximally non-planar configuration +* (TYPE = qloop) +* Same but qluon loop (everything in the adjoint representation) +* (TYPE = gloop) +* Two quark loops with SIZE connecting gluons like a circular ladder. +* (TYPE = qqloop) +* Same with one quark loop and one gluon loop. +* (TYPE = qgloop) +* Same with two gluon loops. +* (TYPE = ggloop) +* The Coxeter graph (diagram with 14 vertices in the adjoint representation +* in which there are no loops with fewer than 6 lines) (TYPE = g14) +* +* One should not choose SIZE larger than 7 or most likely the simplification +* routine cannot simplify the final result completely (in some rare cases +* it can though for SIZE = 8). +* For execution times, see the paper. +* It does get very slow for quarks and SIZE > 7. +* +* Program by J.Vermaseren, 24-may-1997 +* +#include color.h +AutoDeclare Index i,j,k; +CFunction acc; +Symbol x; +.global +G Q{2*`SIZE'} = *...* + **...* + *replace_(i{`SIZE'*2+1},i1); + +G G{2*`SIZE'} = *...* + **...* + *replace_(i{`SIZE'*2+1},i1); + +G QQ`SIZE' = *...* + **...* + *replace_(i{`SIZE'+1},i1,k{`SIZE'+1},k1); + +G QG`SIZE' = *...* + **...* + *replace_(i{`SIZE'+1},i1,k{`SIZE'+1},k1); + +G GG`SIZE' = *...* + **...* + *replace_(i{`SIZE'+1},i1,k{`SIZE'+1},k1); + +* These take too long under valgrind. +*G girth14 = +* f(i1,i2,i3)*f(i1,i4,i5)*f(i2,i6,i7)*f(i3,i8,i9) +* *f(i4,i10,i11)*f(i5,i12,i13)*f(i6,i14,i15)*f(i7,i16,i17) +* *f(i8,i18,i19)*f(i9,i20,i21) +* *f(i10,i21,i15)*f(i13,i19,i14)*f(i17,i11,i18)*f(i12,i16,i20); +* +*G girth24 = +* f(i36,i1,i2)*f(i36,i3,i4)*f(i1,i5,i6)*f(i2,i7,i8) +* *f(i3,i9,i10)*f(i4,i11,i12)*f(i5,i13,i14)*f(i6,i15,i16) +* *f(i7,i17,i18)*f(i8,i19,i20)*f(i9,i21,i22)*f(i10,i23,i24) +* *f(i11,i25,i26)*f(i12,i27,i28)*f(i13,i23,i29)*f(i14,i27,i30) +* *f(i15,i25,i31)*f(i16,i21,i32)*f(i17,i26,i29)*f(i18,i32,i33) +* *f(i19,i31,i34)*f(i20,i22,i30)*f(i24,i34,i35)*f(i28,i33,i35); +* +*G fiveq = T(i1,i2,j1)*T(i2,i3,j2)*T(i3,i1,j3)* +* T(i4,i5,j2)*T(i5,i6,j4)*T(i6,i4,j5)* +* T(i7,i8,j4)*T(i8,i9,j6)*T(i9,i7,j7)* +* T(i10,i11,j6)*T(i11,i12,j1)*T(i12,i10,j8)* +* T(i13,i14,j3)*T(i14,i15,j5)*T(i15,i16,j7)*T(i16,i13,j8); + +Sum i1,...,i{`SIZE'*2},j1,...,j`SIZE',k1,...,k`SIZE'; +.sort + +#call color +#call SORT(tloop-1) +#call adjoint +#call SORT(tloop-2) +.sort +#call simpli +id acc(x?) = x; +*Print +s; +.sort + +* Check results +Local Q10 = - Q10 + + NA*I2R*cR^4 + - 5*NA*I2R*cA*cR^3 + + 35/4*NA*I2R*cA^2*cR^2 + - 155/24*NA*I2R*cA^3*cR + + 125/72*NA*I2R*cA^4 + + 5*d44(cOlpR1,cOlpA1)*cR + - 6*d44(cOlpR1,cOlpA1)*cA + + 1/3*d44(cOlpA1,cOlpA2)*I2R + ; + +Local G10 = - G10 + - 1/36*NA*cA^5 + + 2/3*d44(cOlpA1,cOlpA2)*cA + ; + +Local QQ5 = - QQ5 + - 5/144*NA*I2R^2*cA^3 + + 11/48*d33(cOlpR1,cOlpR2)*cA^2 + - 5/6*d44(cOlpR1,cOlpR2)*cA + + 1/6*d44(cOlpR1,cOlpA1)*I2R + + d55(cOlpR1,cOlpR2) + ; + +Local QG5 = - QG5 + - 5/144*i_*NA*I2R*cA^4 + - 3/4*d44(cOlpR1,cOlpA1)*i_*cA + + 1/12*d44(cOlpA1,cOlpA2)*i_*I2R + ; + +Local GG5 = - GG5 + + 5/144*NA*cA^5 + + 2/3*d44(cOlpA1,cOlpA2)*cA + ; +.sort + +#do ex = {`activeexprnames_'} + #if `ZERO_`ex'' == 0 + #message Error in `ex' + #terminate + #endif +#enddo + +.end +assert succeeded? +*--#] color_tloop : diff --git a/check/forcer/forcer.frm b/check/extra/forcer.frm similarity index 99% rename from check/forcer/forcer.frm rename to check/extra/forcer.frm index 1a0f2fb63..d29bb274a 100644 --- a/check/forcer/forcer.frm +++ b/check/extra/forcer.frm @@ -19,6 +19,7 @@ L F = B ep; P; .end +#pend_if valgrind? assert succeeded? assert result("F") =~ expr(" + ep^-3 * ( 1/24 ) @@ -140,6 +141,7 @@ ModuleOption noparallel; B ep; P; .end +#pend_if valgrind? assert succeeded? assert result("F1") =~ expr(" + ep^-1 * ( - 35/2*z5 ) @@ -267,6 +269,7 @@ ModuleOption noparallel; B ep; P; .end +#pend_if valgrind? assert succeeded? assert result("F1") =~ expr(" + ep^-1 * ( - 35/2*z5 ) diff --git a/check/multithreaded/multithreaded.frm b/check/extra/multithreaded.frm similarity index 97% rename from check/multithreaded/multithreaded.frm rename to check/extra/multithreaded.frm index 491352e8e..e02cd5738 100644 --- a/check/multithreaded/multithreaded.frm +++ b/check/extra/multithreaded.frm @@ -1,4 +1,4 @@ -#:FilePatches 2 +#:FilePatches 16 #:LargePatches 2 #:TermsInSmall 4 @@ -11,7 +11,7 @@ .end *--#[ multithreaded_1 : -#:FilePatches 2 +#:FilePatches 16 #:LargePatches 2 #:TermsInSmall 4 diff --git a/sources/symmetr.c b/sources/symmetr.c index 64a563e1c..cb0518703 100644 --- a/sources/symmetr.c +++ b/sources/symmetr.c @@ -531,7 +531,7 @@ WORD Distribute(DISTRIBUTE *d, WORD first) inc = d->cycle; from = inc + d->n; while ( *inc ) { j++; inc++; } - while ( !*inc && inc < from ) { i++; inc++; } + while ( inc < from && !*inc ) { i++; inc++; } if ( inc >= from ) return(1); d->sign ^= ((i&j)-j+1) & 1; *inc = 0;