vermaseren / form Goto Github PK
View Code? Open in Web Editor NEWThe FORM project for symbolic manipulation of very big expressions
License: GNU General Public License v3.0
The FORM project for symbolic manipulation of very big expressions
License: GNU General Public License v3.0
The following minimal code works with the released 4.1 version on github and older FORM version, but not with 4.1 binaries on the FORM webpage and the current master:
Symbols a, b;
Functions fun, nDUMMY1, nDUMMY2;
Local expr= fun(a)*fun(b) ;
Id nDUMMY1?(?args1) * nDUMMY2?(?args2) = 1;
.sort
Print;
.end
Error message:
TFORM 4.1 (Jan 13 2014) 64-bits 0 workers Run: Wed Mar 19 14:07:27 2014
Symbols a, b;
Functions fun, nDUMMY1, nDUMMY2;
Local expr= fun(a)*fun(b) ;
Id nDUMMY1?(?args1) * nDUMMY2?(?args2) = 1;
Program terminating in thread 0 at replacefuncs.frm Line 4 -->
The bug was introduced by the commit d0a46ff (found out by using git bisect).
In the following example, $a = 1+x-y
is factorized as $a[1] = -1
and $a[2] = 1+x-y
. The overall sign is wrong.
S x,y;
#$a = 1+x-y;
#factdollar $a
#$b = 1
#do i=1,`$a[0]'
* (`$a[`i']')
#enddo
;
#$c = $a - $b; * should be 0
#message $a=`$a'
#do i=0,`$a[0]'
#message $a[`i']=`$a[`i']'
#enddo
#message $b=`$b'
#message $c=`$c'
.end
~~~$a=1-y+x
~~~$a[0]=2
~~~$a[1]=-1
~~~$a[2]=x-y+1
~~~$b=-1+y-x
~~~$c=2-2*y+2*x
[Update] FillExpression
was implemented.
References to expressions in tables doesn't trigger any broadcasting of RHS expressions. (Use of expressions in Fill statements is not recommended and FORM warns.) For example, for an example in Fill statement in the manual,
Table B(1:1);
Local dummy = 1;
.sort
Fill B(1) = dummy;
.sort
Local F = B(1);
Print;
.sort
Drop;
.sort
Local dummy = 2;
.sort
Local F = B(1);
Print;
.end
ParFORM prints F = 0, while the sequential FORM prints F = 1 for the first Print statement and F = 2 for the second.
FillExpression has the same problem that RHS expressions are not broadcast when the master and workers try to fill tables. So, the tables on the workers differ from that on the master and cause troubles. For the following program:
CTable tab(1:2);
S x;
CF f;
L F = <f(1)*x^1>+...+<f(2)*x^2>;
B x;
P;
.sort
FillExpression tab = F(x);
L F1 = tab(1);
L F2 = tab(2);
PrintTable tab;
P;
.end
ParFORM freezes with an error "Element in table is undefined tab(1)".
Just after putinside, some of substitutions for the generated functions don't match:
S x;
CF f;
L F1 = 1+x+x^2;
L F2 =-1-x-x^2;
putinside f, x;
*argument; endargument; * <-- (1)
id f( 1) = 0;
id f(-1) = 0;
id f( x) = 0;
id f(-x) = 0;
id f( x^2) = 0;
id f(-x^2) = 0;
P;
.end
which gives
F1 =
f(1) + f(x);
F2 =
f( - 1);
(F1 and F2 are expected zero.)
Enabling line (1) gives the expected result. Maybe some dirty flag problems?
The same thing occurs for antiputinside:
S x;
CF f;
L F1 = 1+x+x^2;
L F2 =-1-x-x^2;
antiputinside f, x;
*argument; endargument; * <-- (1)
id f( 1) = 0;
id f(-1) = 0;
P;
.end
which gives
F1 =
f(1) + f(1)*x + f(1)*x^2;
F2 =
f( - 1) + f( - 1)*x + f( - 1)*x^2;
The following program crashes in compiling the putinside
statement:
#define N "100000"
S a1,...,`N';
CF f;
L F = a1;
putinside f,a1,...,a`N';
.end
I just record that 2444eda introduces build errors becuase setfile.c is overwritten in an incompatible way.
The following program crashes:
S n;
#$x = n * replace_(n,n+1);
.end
Separated from #42.
Test program: https://gist.githubusercontent.com/tueda/5f83e562854158b5a62f/raw/test1.frm
The slowness comes from the fact that in factorization of expressions the contents are not extracted before calling the general factorization routine. It needs some work:
poly_factorize_expression()
before calling polyfact::factorize()
.The following form program gives memory errors and coredumps:
#-
#-
CFunction TOPO,topo;
CFunction color;
Symbol M1,M2,x,cOlNA,cOlNR,ca,cf,nf,[dabc^2/n],[d4RR/n],[d4RA/n],[d4AA/n];
L Diagrams=
+topo(M1)*color(24*[d4RR/n]*cOlNA*cOlNR^-1+12*ca*[dabc^2/n]+
ca^2*cf*nf)
+topo(M2)*color(24*[d4RA/n]*cOlNA*cOlNR^-1+24*cf^4-72*ca*cf^3
+66*ca^2*cf^2-19*ca^3*cf)
;
.sort
id topo(x?$topo) = 1;
id color(x?$color) = 1;
$color = $color * topo($topo);
.end
Note that the terms inside color() are quite specific: if you remove one, the program passes.
Here is the valgrind log:
==26512== Invalid write of size 4
==26512== at 0x44ABD7: WildDollars (dollar.c:970)
==26512== by 0x4A2322: TestMatch (pattern.c:342)
==26512== by 0x4C3CC9: Generator (proces.c:3523)
==26512== by 0x4C46AA: Generator (proces.c:3760)
==26512== by 0x4BA51B: Processor (proces.c:392)
==26512== by 0x45581E: DoExecute (execute.c:800)
==26512== by 0x47A767: ExecModule (module.c:274)
==26512== by 0x4A9711: PreProcessor (pre.c:884)
==26512== by 0x4062F1: main (startup.c:1519)
==26512== Address 0x627dd48 is 0 bytes after a block of size 200 alloc'd
==26512== at 0x4C29E6F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26512== by 0x52C941: Malloc1 (tools.c:2205)
==26512== by 0x4FAD7F: EndSort (sort.c:696)
==26512== by 0x449658: AssignDollar (dollar.c:425)
==26512== by 0x4C2FB8: Generator (proces.c:3371)
==26512== by 0x4C46AA: Generator (proces.c:3760)
==26512== by 0x4C46AA: Generator (proces.c:3760)
==26512== by 0x4BA51B: Processor (proces.c:392)
==26512== by 0x45581E: DoExecute (execute.c:800)
==26512== by 0x47A767: ExecModule (module.c:274)
==26512== by 0x4A9711: PreProcessor (pre.c:884)
==26512== by 0x4062F1: main (startup.c:1519)
==26512==
==26512== Invalid read of size 4
==26512== at 0x44C053: DolToTerms (dollar.c:1445)
==26512== by 0x4C4190: Generator (proces.c:3605)
==26512== by 0x4495FE: AssignDollar (dollar.c:416)
==26512== by 0x4C2FB8: Generator (proces.c:3371)
==26512== by 0x4C46AA: Generator (proces.c:3760)
==26512== by 0x4C46AA: Generator (proces.c:3760)
==26512== by 0x4BA51B: Processor (proces.c:392)
==26512== by 0x45581E: DoExecute (execute.c:800)
==26512== by 0x47A767: ExecModule (module.c:274)
==26512== by 0x4A9711: PreProcessor (pre.c:884)
==26512== by 0x4062F1: main (startup.c:1519)
==26512== Address 0x627dd48 is 0 bytes after a block of size 200 alloc'd
==26512== at 0x4C29E6F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26512== by 0x52C941: Malloc1 (tools.c:2205)
==26512== by 0x4FAD7F: EndSort (sort.c:696)
==26512== by 0x449658: AssignDollar (dollar.c:425)
==26512== by 0x4C2FB8: Generator (proces.c:3371)
==26512== by 0x4C46AA: Generator (proces.c:3760)
==26512== by 0x4C46AA: Generator (proces.c:3760)
==26512== by 0x4BA51B: Processor (proces.c:392)
==26512== by 0x45581E: DoExecute (execute.c:800)
==26512== by 0x47A767: ExecModule (module.c:274)
==26512== by 0x4A9711: PreProcessor (pre.c:884)
==26512== by 0x4062F1: main (startup.c:1519)
==26512==
==26512== Invalid read of size 4
==26512== at 0x44C39B: DolToTerms (dollar.c:1511)
==26512== by 0x4C4190: Generator (proces.c:3605)
==26512== by 0x4495FE: AssignDollar (dollar.c:416)
==26512== by 0x4C2FB8: Generator (proces.c:3371)
==26512== by 0x4C46AA: Generator (proces.c:3760)
==26512== by 0x4C46AA: Generator (proces.c:3760)
==26512== by 0x4BA51B: Processor (proces.c:392)
==26512== by 0x45581E: DoExecute (execute.c:800)
==26512== by 0x47A767: ExecModule (module.c:274)
==26512== by 0x4A9711: PreProcessor (pre.c:884)
==26512== by 0x4062F1: main (startup.c:1519)
==26512== Address 0x627dd48 is 0 bytes after a block of size 200 alloc'd
==26512== at 0x4C29E6F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26512== by 0x52C941: Malloc1 (tools.c:2205)
==26512== by 0x4FAD7F: EndSort (sort.c:696)
==26512== by 0x449658: AssignDollar (dollar.c:425)
==26512== by 0x4C2FB8: Generator (proces.c:3371)
==26512== by 0x4C46AA: Generator (proces.c:3760)
==26512== by 0x4C46AA: Generator (proces.c:3760)
==26512== by 0x4BA51B: Processor (proces.c:392)
==26512== by 0x45581E: DoExecute (execute.c:800)
==26512== by 0x47A767: ExecModule (module.c:274)
==26512== by 0x4A9711: PreProcessor (pre.c:884)
==26512== by 0x4062F1: main (startup.c:1519)
==26512==
In the following code, FactArg seems never to return. (At least extremely slow.)
CF den;
S ep,w;
L F =
+ den(226492416*ep^4*w - 679477248*ep^4*w^2 + 452984832*ep^4*
w^3 + 452984832*ep^4*w^4 - 679477248*ep^4*w^5 + 226492416*ep^4*
w^6 - 1887436800*ep^5*w + 5775556608*ep^5*w^2 - 4001366016*ep^5
*w^3 - 3774873600*ep^5*w^4 + 5888802816*ep^5*w^5 - 2000683008*
ep^5*w^6 - 1730150400*ep^6*w + 4756340736*ep^6*w^2 - 2592079872
*ep^6*w^3 - 3460300800*ep^6*w^4 + 4322230272*ep^6*w^5 -
1296039936*ep^6*w^6 + 51111788544*ep^7*w - 156153937920*ep^7*
w^2 + 107860721664*ep^7*w^3 + 102223577088*ep^7*w^4 -
158972510208*ep^7*w^5 + 53930360832*ep^7*w^6 - 88394956800*ep^8
*w + 278057189376*ep^8*w^2 - 202534551552*ep^8*w^3 -
176789913600*ep^8*w^4 + 290929508352*ep^8*w^5 - 101267275776*
ep^8*w^6 - 350459265024*ep^9*w + 1065105752064*ep^9*w^2 -
728374444032*ep^9*w^3 - 700918530048*ep^9*w^4 + 1078833709056*
ep^9*w^5 - 364187222016*ep^9*w^6 + 1143994318848*ep^10*w -
3545436782592*ep^10*w^2 + 2514896289792*ep^10*w^3 +
2287988637696*ep^10*w^4 - 3658890608640*ep^10*w^5 +
1257448144896*ep^10*w^6 + 54207184896*ep^11*w - 101166612480*
ep^11*w^2 - 14495514624*ep^11*w^3 + 108414369792*ep^11*w^4 -
39711670272*ep^11*w^5 - 7247757312*ep^11*w^6 - 3522057732096*
ep^12*w + 10869824028672*ep^12*w^2 - 7651417128960*ep^12*w^3 -
7044115464192*ep^12*w^4 + 11173474861056*ep^12*w^5 -
3825708564480*ep^12*w^6 + 3387722563584*ep^13*w -
10557767811072*ep^13*w^2 + 7564645367808*ep^13*w^3 +
6775445127168*ep^13*w^4 - 10952367931392*ep^13*w^5 +
3782322683904*ep^13*w^6 + 1380798431232*ep^14*w - 4224234553344
*ep^14*w^2 + 2925275381760*ep^14*w^3 + 2761596862464*ep^14*w^4
- 4306073812992*ep^14*w^5 + 1462637690880*ep^14*w^6 -
3140694835200*ep^15*w + 9744207052800*ep^15*w^2 - 6925634764800
*ep^15*w^3 - 6281389670400*ep^15*w^4 + 10066329600000*ep^15*w^5
- 3462817382400*ep^15*w^6 + 1087163596800*ep^16*w -
3382286745600*ep^16*w^2 + 2415919104000*ep^16*w^3 +
2174327193600*ep^16*w^4 - 3503082700800*ep^16*w^5 +
1207959552000*ep^16*w^6)
;
factarg den;
.end
The latest version of FORM freezes for
V a;
CF rat;
PolyRatFun rat;
L F = rat(a.a,1);
P +s;
.end
while older versions printed an error message:
ERROR: polynomials and polyratfuns must contain symbols only
This is an example that ParFORM freezes/aborts in #FactDollar. It seems that the problem occurs in workers.
S x,y;
S dummy1,dummy2;
*L F = 1+x+y; * OK
L F = 1-x+y; * BAD
*L F = 1+x-y; * BAD
*L F = 1-x-y; * OK
*L F = -1+x+y; * OK
*L F = -1-x+y; * BAD
*L F = -1+x-y; * BAD
*L F = -1-x-y; * OK
id dummy1 = dummy2; * <-- any executable statements
.sort
#$F = F;
*.sort; * <-- (1) workaround
#factdollar $F
#if `$F[0]' == 1
#message $F[0] = `$F[0]'
#message $F = `$F'
#else
#do i=0,`$F[0]'
#message $F[`i'] = `$F[`i']'
#enddo
#endif
.end
==7665== Invalid read of size 4
==7665== at 0x4924F7: Generator (proces.c:3013)
==7665== by 0x42CD68: DollarFactorize (dollar.c:3178)
==7665== by 0x4866C5: DoFactDollar (pre.c:6239)
==7665== by 0x48C329: PreProcessor (pre.c:857)
==7665== by 0x4BC3FE: main (startup.c:1519)
==7665== Address 0x0 is not stack'd, malloc'd or (recently) free'd
Inserting .sort
at line (1) somehow works as a workaround. ParFORM 4.1 (Aug 18 2015)
didn't have this problem.
After commit 59aca15, the optimization fails with very trivial expressions like:
Local expr=1;
.sort
Format O2;
#Optimize expr;
.end
Error message:
test.frm Line 5 ==> Illegal empty value for preprocessor variable optimscheme_
The current git master and the "4.1" FORM binaries (build date Jan 13 2014) supplied on the FORM website are affected, but not the 4.1 release on github.
As we are using FORM in an automated environment, it would make additional effort to catch trivial expressions.
Below is a FORM file with a bug description.
CF PG,PQx, VQQG;
*
* PG is a gluon propagator
* PQx is a cut quark propagator
* VQQG is a quark-quark-gluon veretex
*
T S(symmetric);
I s0,...,s99;
I v1,...,v99;
V k0,...,k99;
V p0,...,p9999;
CF Sigma;
*
* Expression for the gluon self-energy (with one quark loop)
*
L RESULT = PG(S(v17,v18),k3 + k4) * PG(S(v37,v38),k3 + k4) * VQQG(s2,k4,s4,k3,v17, - k3 - k4) * VQQG(s24,k3,s22,k4,v37, - k3 - k4) * PQx(s2,s22,k4) *PQx(s4,s24,k3);
id PG(S(v19?,v2?),p12?)*VQQG(s5?,p5?,s7?,p7?,v2?,p2?)*PQx(s5?,s6?,p56?)*PQx(s7?,s8?,p78?)*VQQG(s8?,p8?,s6?,p6?,v3?,p86?)*PG(S(v3?,v4?),p34?) = Sigma(p34);
*
* ^
* |
* BUG
*
* The transformation rule above collects a gluon propagator
* into a simple expression `Sigma(k3+k4)'. The current version
* works as expected.
*
* If you, however, change index `v19?' to `v1?' the rule above
* works not as expected.
*
* > form -v
* FORM 4.1 (Jan 13 2014) 64-bits
*
* > uname -a
* Linux golf.gituliar.org 3.14.4-1-ARCH #1 SMP PREEMPT Tue May 13 16:41:39 CEST 2014 x86_64 GNU/Linux
*
.sort
Print +sss;
.end
Dear developers,
Is there a factor of 4 missing in front of the \epsilon near line 62 of doc/manual/metric.tex?
Cheers,
Gauthier
When printing expressions in Mathematica
format sometimes output contains newlines (see example below) which are treated by Mathematica as end of the expression. Because of that Mathematica ignores everything after the first newline.
My solution is to wrap a whole output expression in parentheses, e.g. F = ( <expr> )
, but you of course may have other ideas.
CF f,g;
S x;
L F = (x+1)^2*(f(x)+g(x))^5;
Format Mathematica;
Bracket x;
Print +s;
.end
"On compress, gzip, n" can lead an abnormal termination with the parallelization of ParFORM.
The following program gave me an unexpected result:
S x,a;
L F = a;
if (match(x?$x));
P "%t: matched (%$)", $x;
endif;
.sort
#message x=`$x'
.end
The output was
+ a: matched (***)
~~~x=
If I put many
option to the match
function,
if (match(many,x?$x));
then it works well:
+ a: matched (a)
~~~x=a
This is probably an OS-related issue rather than a FORM bug, and maybe we cannot make any improvements, but still I would like to put a note about it. I am using a Desktop PC with Scientific Linux 6.6, x86_64, 7804MB Mem + 7967MB Swap. The problem I hit is, as a simple example,
#:MaxTermSize 2M
#:WorkSpace 2G
#system echo OK
.end
fails at use of #system
:
foo.frm Line 4 ==> System call returned with error condition
If I remove the settings of MaxTermSize
and WorkSpace
, the program works well. A similar situation was already described in this post in the forum. But now the origin of the problem looks like: if a program allocates big memory blocks, then the system call for system()
fails.
Note that the above program consumes only a small memory space (as you can see, for example, by top
). GNU time
utility reports the maximum resident set size is 1720KB. But actually the program allocates a very large memory space. valgrind
reports 14GB memory blocks are still reachable (bigger than Mem+Swap).
Connected to the fix in the manual (f11fa12), the manual now says
Technically #ifdef `VAR' and #if ( isdefined(VAR) ) are the same.
To be exact, this statement is not true when VAR
is defined but empty.
#define VAR ""
#ifdef `VAR'
#message VAR is defined (1)
#endif
#if (isdefined(VAR))
#message VAR is defined (2)
#endif
.end
prints only
~~~VAR is defined (2)
Behaviour of both #ifdef
and isdefined
are more or less reasonable to me. (At least changing the behaviour of #ifdef
will cause disasters in many of my codes.) Maybe the manual should be changed a bit?
Hi,
I have cloned the git repo and am compiling with gcc (Ubuntu 4.8.2-19ubuntu1)
. During compilation, I get one warning
In file included from tools.c:54:0:
tools.c: In function โTruncateFileโ:
form3.h:422:31: warning: ignoring return value of โftruncateโ, declared with attribute warn_unused_result [-Wunused-result]
#define Utruncate(f) ftruncate(f->descriptor,0);
^
tools.c:1401:3: note: in expansion of macro โUtruncateโ
Utruncate(f);
^
Probably unrelated, when I try to make check
, I get
/bin/bash:1: Invalid char `\x7F' in expression
/bin/bash:1: Invalid char `\x02' in expression
/bin/bash:1: Invalid char `\x01' in expression
/bin/bash:1: Invalid char `\x01' in expression
/bin/bash:1:in `<main>': uninitialized constant ELF (NameError)
make[3]: *** [form.rb.log] Error 1
make[3]: Leaving directory `/home/bijancn/form/check'
make[2]: *** [check-TESTS] Error 2
Trying to make manual.pdf
, I stumpled upon a problem with manualdate.tex
. With my locale I get 22 Mai 2014
with date +"%d %b %Y"
which is not accepted by date -d ('invalid date'). A quick fix that allowed me to build the manual was to use date -I
(ISO format) instead of date +"%d %b %Y"
in the Makefile.am
. Maybe you want to use this.
When I try a trivial example, it seems to run fine, except I get
Format 03;
... Too small value for linesize corrected to 39
#optimize expr
Print;
.end
This might be connected to the failed make check
? I could only trace this problem to FG.cTable
but I don't know how to fix it. I have plenty of space for windows so a linesize of 39 looks quite annoying.
I am trying to switch from FactArg
to FactDollar
to avoid the curse of MaxTermSize
. The major problem is that FactDollar
is really much slower than FactArg
.
I put a test program at https://gist.githubusercontent.com/tueda/5f83e562854158b5a62f/raw/test1.frm. The file contains two expressions F1
and F2
. The timing I obtained for F1
was
~~~factarg : .01 sec
~~~#factdollar : 7.74 sec
~~~factdollar : 7.81 sec
~~~factorize : 7.75 sec
and the timing for F2
was
~~~factarg : .01 sec
~~~#factdollar : 350.05 sec
~~~factdollar : 350.31 sec
~~~factorize : 356.11 sec
Maybe the recent improvements do not apply for them?
Here I just record what I encountered for make check
within Cygwin 1.7.30 (both x86_64 and i686) on Windows 7 (SP1, x86_64):
make check-TESTS
make[1]: Entering directory '/home/tueda/tmp/form-4.1/check'
Run options:
# Running tests:
EEEEEEE./form.rb:87: [BUG] Segmentation fault
ruby 1.9.3p545 (2014-02-24) [x86_64-cygwin]
-- Control frame information -----------------------------------------------
c:0026 p:---- s:0108 b:0108 l:000107 d:000107 CFUNC :close
c:0025 p:0233 s:0105 b:0105 l:000ae0 d:000ae0 METHOD ./form.rb:87
c:0024 p:0018 s:0093 b:0093 l:000092 d:000092 METHOD /home/tueda/tmp/form-4.1/check/examples.rb:1070
c:0023 p:0073 s:0090 b:0090 l:000089 d:000089 METHOD /usr/lib/ruby/1.9.1/minitest/unit.rb:949
c:0022 p:0025 s:0084 b:0084 l:000083 d:000083 METHOD /usr/lib/ruby/1.9.1/test/unit/testcase.rb:17
c:0021 p:0090 s:0080 b:0080 l:000068 d:000079 BLOCK /usr/lib/ruby/1.9.1/minitest/unit.rb:787
c:0020 p:---- s:0074 b:0074 l:000073 d:000073 FINISH
c:0019 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :map
c:0018 p:0124 s:0069 b:0069 l:000068 d:000068 METHOD /usr/lib/ruby/1.9.1/minitest/unit.rb:780
c:0017 p:0020 s:0061 b:0060 l:000050 d:000059 BLOCK /usr/lib/ruby/1.9.1/test/unit.rb:565
c:0016 p:---- s:0056 b:0056 l:000055 d:000055 FINISH
c:0015 p:---- s:0054 b:0054 l:000053 d:000053 CFUNC :each
c:0014 p:0053 s:0051 b:0051 l:000050 d:000050 METHOD /usr/lib/ruby/1.9.1/test/unit.rb:563
c:0013 p:0189 s:0045 b:0045 l:000044 d:000044 METHOD /usr/lib/ruby/1.9.1/minitest/unit.rb:746
c:0012 p:0013 s:0035 b:0035 l:000034 d:000034 METHOD /usr/lib/ruby/1.9.1/minitest/unit.rb:909
c:0011 p:0012 s:0032 b:0032 l:000023 d:000031 BLOCK /usr/lib/ruby/1.9.1/minitest/unit.rb:896
c:0010 p:---- s:0029 b:0029 l:000028 d:000028 FINISH
c:0009 p:---- s:0027 b:0027 l:000026 d:000026 CFUNC :each
c:0008 p:0068 s:0024 b:0024 l:000023 d:000023 METHOD /usr/lib/ruby/1.9.1/minitest/unit.rb:895
c:0007 p:0029 s:0020 b:0020 l:000019 d:000019 METHOD /usr/lib/ruby/1.9.1/minitest/unit.rb:884
c:0006 p:0022 s:0016 b:0016 l:000015 d:000015 METHOD /usr/lib/ruby/1.9.1/test/unit.rb:21
c:0005 p:0033 s:0012 b:0011 l:0012e8 d:000010 BLOCK /usr/lib/ruby/1.9.1/test/unit.rb:326
c:0004 p:0036 s:0009 b:0009 l:000008 d:000008 METHOD /usr/lib/ruby/1.9.1/test/unit.rb:27
c:0003 p:0026 s:0006 b:0006 l:0012e8 d:000005 BLOCK /usr/lib/ruby/1.9.1/test/unit.rb:325
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
c:0001 p:0000 s:0002 b:0002 l:0005c8 d:0005c8 TOP
-- Ruby level backtrace information ----------------------------------------
/usr/lib/ruby/1.9.1/test/unit.rb:325:in `block in autorun'
/usr/lib/ruby/1.9.1/test/unit.rb:27:in `run_once'
/usr/lib/ruby/1.9.1/test/unit.rb:326:in `block (2 levels) in autorun'
/usr/lib/ruby/1.9.1/test/unit.rb:21:in `run'
/usr/lib/ruby/1.9.1/minitest/unit.rb:884:in `run'
/usr/lib/ruby/1.9.1/minitest/unit.rb:895:in `_run'
/usr/lib/ruby/1.9.1/minitest/unit.rb:895:in `each'
/usr/lib/ruby/1.9.1/minitest/unit.rb:896:in `block in _run'
/usr/lib/ruby/1.9.1/minitest/unit.rb:909:in `run_tests'
/usr/lib/ruby/1.9.1/minitest/unit.rb:746:in `_run_anything'
/usr/lib/ruby/1.9.1/test/unit.rb:563:in `_run_suites'
/usr/lib/ruby/1.9.1/test/unit.rb:563:in `each'
/usr/lib/ruby/1.9.1/test/unit.rb:565:in `block in _run_suites'
/usr/lib/ruby/1.9.1/minitest/unit.rb:780:in `_run_suite'
/usr/lib/ruby/1.9.1/minitest/unit.rb:780:in `map'
/usr/lib/ruby/1.9.1/minitest/unit.rb:787:in `block in _run_suite'
/usr/lib/ruby/1.9.1/test/unit/testcase.rb:17:in `run'
/usr/lib/ruby/1.9.1/minitest/unit.rb:949:in `run'
/home/tueda/tmp/form-4.1/check/examples.rb:1070:in `test1'
./form.rb:87:in `execute'
./form.rb:87:in `close'
-- Other runtime information -----------------------------------------------
* Loaded script: ./form.rb
* Loaded features:
0 enumerator.so
1 /usr/lib/ruby/1.9.1/x86_64-cygwin/enc/encdb.so
2 /usr/lib/ruby/1.9.1/x86_64-cygwin/enc/shift_jis.so
3 /usr/lib/ruby/1.9.1/x86_64-cygwin/enc/trans/transdb.so
4 /usr/lib/ruby/1.9.1/rubygems/defaults.rb
5 /usr/lib/ruby/1.9.1/x86_64-cygwin/rbconfig.rb
6 /usr/lib/ruby/1.9.1/rubygems/deprecate.rb
7 /usr/lib/ruby/1.9.1/rubygems/exceptions.rb
8 /usr/lib/ruby/1.9.1/rubygems/custom_require.rb
9 /usr/lib/ruby/1.9.1/rubygems.rb
10 /usr/lib/ruby/1.9.1/open3.rb
11 /usr/lib/ruby/1.9.1/optparse.rb
12 /usr/lib/ruby/1.9.1/minitest/unit.rb
13 /usr/lib/ruby/1.9.1/prettyprint.rb
14 /usr/lib/ruby/1.9.1/pp.rb
15 /usr/lib/ruby/1.9.1/test/unit/assertions.rb
16 /usr/lib/ruby/1.9.1/test/unit/testcase.rb
17 /usr/lib/ruby/1.9.1/test/unit.rb
18 /home/tueda/tmp/form-4.1/check/examples.rb
19 /home/tueda/tmp/form-4.1/check/parser.rb
20 /home/tueda/tmp/form-4.1/check/symmetrize.rb
21 /home/tueda/tmp/form-4.1/check/table.rb
[NOTE]
You may have encountered a bug in the Ruby interpreter or extension libraries.
Bug reports are welcome.
For details: http://www.ruby-lang.org/bugreport.html
/bin/sh: line 5: 6516 Aborted (core dumped) /usr/bin/ruby -I . ${dir}$tst
FAIL: form.rb
===============================
1 of 1 test failed
Please report to [email protected]
===============================
Makefile:294: recipe for target 'check-TESTS' failed
There are two problems:
strace
differs from that on Linux. It just ignores the -ff
option. Moreover, the system call exit_group
is not called on Cygwin, so the return_value
method always fails.Sec_15
takes about 10 seconds under the strace
run. (The output looks OK.) So the form.rb
often tries to kill the process due to TIMEOUT=10
, and somehow causes a segfault of Ruby at closing @outputstream
(maybe still used by the process being killed?).I was just trying some tricky things and found the following code makes FORM freeze:
#define CALL(a) "
#call Test(`~a')
"
#procedure Test(a)
#message a=`a'
#endprocedure
`CALL(1)'
.end
It seems to be an interference of the variables with the same name "a" between calling the procedure and the delayed substitution.
A workaround can be (1) to use different names:
#define CALL(a1) "
#call Test(`~a1')
"
#procedure Test(a)
#message a=`a'
#endprocedure
`CALL(1)'
.end
or (2) not to give the arguments for the procedure (although it is a bit mysterious why it works):
#define CALL(a) "
#call Test
"
#procedure Test
#message a=`a'
#endprocedure
`CALL(1)'
.end
Sometimes the Exit statement causes strange things with TFORM. The following program should quit immediately,
S a,x1,...,x9;
L F = a*(x1+...+x9);
*L F = a+(x1+...+x9);
.sort
if (count(a,1)) exit;
.end
but for i in {1..100}; do tform -w4 test.frm; done
(in bash) easily gets stuck. I also got "double free or corruption (fasttop)" errors from glibc.
Because L F = a+(x1+...+x9)
, i.e., only one term with "a", doesn't lead this problem, I guess it comes from that two or more threads try to exit.
FORM fails to preprocess the following program and gives an error "Arguments of macro bar do not match".
#define foo
#define bar(a) "`~a'"
#undefine foo
L F = `bar(1)';
P;
.end
The simple program:
#$C=0;
#write "TEST %$",$C;
.end
crashes in form -y with the error:
write instruction: $C has not been defined
Normal form runs fine.
Problem
I'm not sure whether or not intentionally #(re)define
and #write
were designed to accept strings containing linefeeds (because the manual doesn't mention such cases), but I think this undocumented feature could be useful. There is a problem about linefeeds in the format string of #write
. They don't reset the internal counter for characters in the line, i.e.,
Format fortran;
#define decl "
double precision a1,a2,a3,a4,a5,a6,a7,a8,a9
double precision b1,b2,b3,b4,b5,b6,b7,b8,b9
"
#write "`decl'"
prints
double precision a1,a2,a3,a4,a5,a6,a7,a8,a9
double precisio
& n b1,b2,b3,b4,b5,b6,b7,b8,b9
This is a valid Fortran code but the line break in the second line is not intended.
Similar things can occur in use of #show
and Print "..."
.
Suggestion
For #write
, change writeToChannel
such that LINEFEED
is treated as \n
. It can be archived by inserting 2 lines around pre.c:5722:
diff --git a/sources/pre.c b/sources/pre.c
index 0d8f1fa..932ca5c 100644
--- a/sources/pre.c
+++ b/sources/pre.c
@@ -5719,9 +5719,11 @@ int writeToChannel(int wtype, UBYTE *s, HANDLERS *h)
to[-2] = '&';
}
}
+ if ( *fstring == LINEFEED ) goto linefeed;
if ( *fstring == '\\' ) {
fstring++;
if ( *fstring == 'n' ) {
+linefeed:
num = to - Out;
WriteString(wtype,Out,num);
to = Out;
For #show
and Print "..."
, MesPrint
needs modifications for the format string and for inserted strings by %s
around message.c:223 and 343:
diff --git a/sources/message.c b/sources/message.c
index 4ce11ba..7913606 100644
--- a/sources/message.c
+++ b/sources/message.c
@@ -220,8 +220,13 @@ va_dcl
}
*/
else if ( *s != '%' ) {
+ if ( *s == LINEFEED ) {
+ s++;
+ goto linefeed;
+ }
*t++ = *s++;
if ( t >= stopper ) {
+linefeed:
num = t - Out;
WriteString(ERROROUT,(UBYTE *)Out,num);
num = 0; t = Out;
@@ -335,6 +340,13 @@ va_dcl
else if ( *s == 's' ) {
u = va_arg(ap,char *);
while ( *u ) {
+ if ( *u == LINEFEED ) {
+ u++;
+ num = t - Out;
+ WriteString(ERROROUT,(UBYTE *)Out,num);
+ t = Out;
+ continue;
+ }
if ( t >= stopper ) {
num = t - Out;
WriteString(ERROROUT,(UBYTE *)Out,num);
I think hopefully these changes don't break any existing programs and don't cause any major performance problems.
Related problem
By the way, the manual says \n
can be used for a linefeed for Print
statement, but it doesn't work.
L F = 1;
P "a\nb";
.end
just prints
anb
For this, it seems that compcomm.c:1528 needs modifications. (Just removing the if
line is OK or has some side effects?)
If I run the following program, which is basically a test example heavily using the Collect statement, with -w3 or more threads in TFORM, something wrong often happens, like "Unexpected code in ReNumber" or just freezing, probably depending on some race condition:
On fewerstats;
* The problem size.
#ifndef `N'
#define N "8"
#endif
#message N=`N'
S x1,...,x19;
CF f1,f2;
L F = (x1+...+x19)^`N';
.sort
* Repeat Bracket-Collect.
#do i=1,9
B x`i',x1`i';
.sort:B`i';
Collect, f1, f2;
.sort:Collect`i';
id f1(x1?) = x1;
id f2(x2?) = x2;
#enddo
* Check the result.
.sort
#do i=1,19
id x`i' = 1;
#enddo
.sort
Drop F;
L ZERO = F - 19^`N';
.sort
#if `ZERO_' == 0
#message FAILED
#terminate 1
#endif
.sort
#message OK
.end
I also ran the program with -w0, -w1, -w2 more than 100 times for each case, but I haven't experienced any problems. I guess there might be a thread unsafe code around SortBot(?)
This issue was found originally in a discussion with Matthias Steinhauser.
Description of the following features/behaviour are still missing in the reference manual.
#-
#$v = 2;
L A = $v^(1);
L B = $v^1;
Print +s;
.end
The above program yields
A =
+ 1
;
B =
+ 2
;
I was thinking about test suites in check
directory. As in #15, it doesn't work in Cygwin or other UNIX systems because it uses strace
. Moreover, in Jens's test suites, one should write a test program in Ruby language and it could be a hurdle why no one writes tests for make check
. So, I made a prototype of new test suites, which is designed as
strace
,The implementation is still done in Ruby, though a similar program can be written in Perl etc.
I made a (temporary) repository for it. You can clone it by
git clone https://github.com/tueda/test-form-check2.git
which should make a directory test-form-check2
. After entering check2
subdirectory in it, you can execute check.rb
.
cd test-form-check2
cd check2
./check.rb
By default form
in $PATH
is used. You may try it with tform
(with -w4 by default)
./check.rb tform
or you can explicitly specify the path to the form/tform/parform binary.
./check.rb /path/to/form
As I wrote in #17, #18, #19, some tests are known to fail. form
fails for examples.frm#Dictionaries_1
. In addition to it, tform
fails for examples.frm#PolyandFact_11
. parform
fails for examples.frm#Sta_Fill_2
and examples.frm#Sta_Fill_4
.
In this test suite, tests are provided in *.frm files, and one test is given as a fold. A typical example is
*--#[ TestID :
* FORM program here.
S x;
L F = (1+x)^2;
P;
.end
# Ruby program after ".end" to check the result.
assert succeeded?
assert result("F") =~ terms("1+2*x+x^2")
*--#] TestID :
The block before .end
is regarded as a FORM program, while the block after .end
is regarded as a code block in Ruby to check the output. In this example, succeeded?
checks if the FORM program ran successfully without any errors, and result("F") =~ terms("1+2*x+x^2")
checks if the whole output for F
by Print
statement matches with a string 1+2*x+x^2
(whitespaces including new lines are ignored).
Each fold is actually translated to a Ruby unit test class, so TestID
should be a valid identifier name and must be unique (maybe this rule can be relaxed).
If any Ruby code is not given after .end
, it's equivalent to assert succeeded?
by default. So just writing a FORM test program can be itself a test program for this test suite.
Putting the following code in each *.frm file,
#ifndef `TEST'
#message Use -D TEST=XXX
#terminate
#else
#include `NAME_' # `TEST'
#endif
.end
one can run a test as a pure FORM program like
form -D TEST=TestID test.frm
Actually, examples.frm
and fixes.frm
in the test suite have this code in the header. For example,
form -D TEST=Dictionaries_1 examples.frm
runs the FORM program part of the corresponding test, for which form
currently fails.
When I tried to see what expressions are defined in a FORM program by on names
, I got a segfault. The situation can be simplified as follows:
On allnames;
I mu;
.end
gives, with valgrind,
...
Symbols
i_#i pi_ coeff_ num_ den_ xarg_ dimension_ factor_ sep_
Indices
==22722== Use of uninitialised value of size 8
==22722== at 0x55552D: StrCopy (sch.c:69)
==22722== by 0x5573D7: WriteLists (sch.c:877)
==22722== by 0x4537DE: DoExecute (execute.c:760)
==22722== by 0x478BB2: ExecModule (module.c:274)
==22722== by 0x50FB3A: PreProcessor (pre.c:884)
==22722== by 0x572A7C: main (startup.c:1519)
==22722==
==22722== Invalid read of size 8
==22722== at 0x444377: FindIndex (dict.c:313)
==22722== by 0x5573C5: WriteLists (sch.c:877)
==22722== by 0x4537DE: DoExecute (execute.c:760)
==22722== by 0x478BB2: ExecModule (module.c:274)
==22722== by 0x50FB3A: PreProcessor (pre.c:884)
==22722== by 0x572A7C: main (startup.c:1519)
==22722== Address 0x561cb80 is 16 bytes after a block of size 768 alloc'd
==22722== at 0x4A06A2E: malloc (vg_replace_malloc.c:270)
==22722== by 0x59A053: Malloc1 (tools.c:2205)
==22722== by 0x59A68C: FromVarList (tools.c:2684)
==22722== by 0x480EC9: AddDollar (names.c:2302)
==22722== by 0x5710D0: StartVariables (startup.c:880)
==22722== by 0x572962: main (startup.c:1463)
==22722==
iarg_ mu
Vectors
parg_
...
The "Use of uninitialised value" warning is from iarg_
(so on allnames
) and could be harmless, it just copies uninitialied values that won't be used later. I feel "Invalid read" more dangerous.
Currently make check
fails due to a bug introduced in merging the dictionary branch. A test program is
I mu;
CF f;
L F = f(mu);
P;
.end
which somehow prints
F =
f(i_);
The following program doesn't make any sense in practice (.global just saves declarations), but it causes a segmentation fault:
Global F = 1;
.global
Local G = F;
.end
Some functionalities of dictionaries in the manual seems not to work. (Or it's still incomplete?)
Adding a function into a dictionary,
CF f;
#opendictionary test
#add f: "\ln"
#closedictionary
.end
gives a segfault.
Indices are not correctly translated.
T t;
Indices mu,nu,ro,si;
#opendictionary test
#add mu: "\mu"
#add nu: "\nu"
#add ro: "\rho"
* #add si: "\sigma"
#closedictionary
L F = t(mu,nu,ro,si);
L G = t(mu,nu,ro);
#usedictionary test
P;
.end
gives
F =
t(mu,nu,ro,\rho);
G =
t(mu,nu,ro);
TFORM terminates abnormally with the following program regardless of the number of threads:
S x,y;
L F = 1/2;
* It fails also for an factorized expression in the manual.
* LF F = -0*3*(x+1)*(x+2)/2*0*((x+3)*(x+4));
P;
.sort
Factorize F;
P;
.end
From using Valgrind, it seems that POLY_GETIDENTIFY(a.factor[0])
in poly_fix_minus_signs
is invalid in this case.
The following simple example generates an infinite loop in the Print statement:
S ep;
CF rat;
PolyRatFun rat(expand,ep,6);
L F = rat(ep,ep);
Print;
.end
and when multiplied, it freezes:
S ep;
CF rat;
PolyRatFun rat(expand,ep,6);
L F =rat(1,1)*rat(ep,ep);
.end
Although it is natural that FORM can't handle set elements consisting of more then one term, like {a+1}
, FORM actually accepts and misinterpret such elements. For example,
On names;
S a,x;
CF f;
L F = <f(a-1)>+...+<f(a+1)> + <f(-1)>+...+<f(1)>;
if (match(f(x?{a+1}))) discard;
P;
.end
gives
Sets
{}: a -1
F =
f( - 1 + a) + f(1 + a) + f(0) + f(1);
If the user gives {2*a}
, FORM claims it's an illegal object for set elements. It would be worth to show the same error message and abort the program also for {a+1}
.
Add actual releases for form, including the binaries.
The reference manual says the IntoHide statement without any specifications of expression names makes all active expressions being put into the hidden storage at the end of the module, but somehow it is not implemented to do so in SetExpr(). Actually in the following example the expression F remains as an active local expression:
L F = 1;
.sort
IntoHide;
.sort
On names;
P;
.end
A trivial workaround is to specify all expression names, or to switch to Hide instead of IntoHide.
L F1 = 1;
ModuleOption inparallel;
.sort
#message ZERO_F1 = `ZERO_F1'
#message ZERO_ = `ZERO_'
.end
prints 0
and 1
in TFORM, but should print 0
and 0
as (Par)FORM does.
The settings for intel compilers are a bit outdated and cause warnings about deprecated options.
Here is a tiny patch for Makefile.am, which I used for successful builds recently:
diff --git a/sources/Makefile.am b/sources/Makefile.am
index 7c22084..1b61641 100644
--- a/sources/Makefile.am
+++ b/sources/Makefile.am
@@ -128,10 +128,10 @@ if ONAPPLE
COMPILEFLAGS += -Wall -ipo -O3 -no-prec-div
else
if OPTPENTIUM
-COMPILEFLAGS += -Wall -ipo -O3 -no-prec-div -xP
+COMPILEFLAGS += -Wall -ipo -O3 -no-prec-div -xHost
else
if OPTOPTERON
-COMPILEFLAGS += -Wall -ipo -O3 -no-prec-div -xP
+COMPILEFLAGS += -Wall -ipo -O3 -no-prec-div -xHost
else
COMPILEFLAGS += -Wall -ipo -O3
endif
Add a new website and update info
The following code prints a 20 chars wide result, but in normal
format, while it is supposed to be Mathematica
format.
CF f,g;
S x;
L F = (f(x)+g(x))^5;
Format Mathematica;
Format 20;
Print;
.end
Hello,
The following form program causes a segmentation fault:
Symbol x;
Local expr = x;
Bracket x;
Print;
.sort
Format O3;
#optimize expr
Print;
.end
If the bracket is nontrivial,
Symbol x,y;
Local expr = x*(12+y);
the program runs fine.
This issue also occurred with Format O0, but that has been fixed with commit 8ee418f (I think)
The following code with mixed commutative and non-commutative variables generates too many intermediate terms:
CF a;
NF d, e;
L A = (a+d+e)^10;
.end
Time = 0.03 sec Generated terms = 59049
A Terms in output = 2047
Bytes used = 89916
The solution is simple: split the terms into a group of commutative terms and non-commutative terms, compute the binonium, and multiply the results. Alternatively, replace all the non-commutative terms by a placeholder.
CF a;
NF d, e;
L B = (a+d)^10;
id d = (d+e);
Print +s;
.end
Time = 0.04 sec Generated terms = 2047
B Terms in output = 2047
Bytes used = 89916
This should be done internally.
The following program crashes without any useful messages in the Id-statement (actually no match with F):
#-
* on Linux x86_64
#:maxtermsize 40000
#:workspace 40000000
#define N "700"
#define M "200"
CF Z,f,acc;
S n1,...,n`N';
S a1,...,a`N';
L F = Z(0) * f(<acc(n1,a1)>,...,<acc(n`N',a`N')>);
*L G = Z(0) * f(<acc(n1,a1)>,...,<acc(n`N',a`N')>,acc(1,1));
* Comsume the workspace.
#do i=1,`M'
id Z(?a) = Z(?a);
#enddo
id f(?a,acc(a1?,1),?b) = f(acc(a1,1),?a,?b);
.end
FORM 4.1 (Apr 24 2015) 64-bits Run: Fri Jun 5 15:47:24 2015
#-
Program terminating at foo.frm Line 16 -->
0.03 sec out of 0.03 sec
It looks like due to a shortage of the workspace, because setting M=100 makes the program work well.
For example, the following code makes FORM enter an infinite loop at FindVar
and never returns.
S x;
CF f;
L F = f(1+x);
if (occurs(x));
P "x occurs in %t";
endif;
.end
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.