vermaseren / form

The FORM project for symbolic manipulation of very big expressions
GNU General Public License v3.0
982 stars 118 forks source link

A #do loop over variables from a fold? #448

Open vsht opened 1 year ago

vsht commented 1 year ago

Dear FORM developers and users,

I'm wondering, whether one can use a preprocessor #do loop over a set of strings, when these strings come from a fold. For example, I could have a file lib.h with

*--#[ topoNames:
topology1,
topology2,
topology3,
topology4,
topology5,
topology6,
topology7,
topology8,
topology9,
topology10,
topology11,
topology12,
topology13
*--#] topoNames:

and then try to run something like

off statistics;

CF 
#include lib.h #topoNames
;

.sort
on names;

#do i={
#include lib.h #topoNames
}
CF new`i';
#enddo

.end

The expected behavior would be to have newtopology1, newtopology2, ... defined as commutative functions. Unfortunately, this doesn't seem to work as expected. The explicit code

#do i={topo1,topo2,topo3}
CF new`i';
#enddo

works, though.

So I'm curious if it's my misunderstanding of the syntax and if not, whether one could come up with some workaround to make #do work with folds as I would like it to.

Cheers, Vlad

tueda commented 1 year ago

I think you would already hit troubles when using the for-each-ish #do-loop with line breaks:

#do i={
topo1,topo2,topo3
}
#message `i'
#enddo
.end
vsht commented 1 year ago

True, however this still works

#do i={\
topo1,topo2,topo3
\
}
CF new`i';
#enddo

while this doesn't:

#do i={\
#include lib.h #topoNames
\
}
CF new`i';
#enddo
jodavies commented 1 year ago

You can do something like this:

#pipe echo "#define LOOPVARS \"$(grep topology lib.h | tr -d \"\\n\" )\""

#do i = {`LOOPVARS'}

If the contents of the fold don't have such "reliable" names or the file has loads of other stuff you can just print the whole fold contents with some bash construction...

tueda commented 1 year ago

Version 5.0 may be a perfect timing to change the #do-loop behaviour in such a way that it can handle multiple lines with line breaks (if it is possible; I haven't dived into the source code yet).

On the other hand, your fold contents look automatically generated. If this is true, maybe you can regenerate (or convert) it in the following way:

main.frm:

#redefine FOO(a) "`~a'"
CF
#include lib.h #topoNames
;

#redefine FOO(a) "CF new`~a';"
#include lib.h #topoNames

.sort
On names;
.end

lib.h:

*--#[ topoNames:
`FOO(topology1)'
`FOO(topology2)'
`FOO(topology3)'
*--#] topoNames:

You could also add some attributes like

*--#[ topoNames:
`FOO(topology1,1,A)'
`FOO(topology2,2,B)'
`FOO(topology3,3,C)'
*--#] topoNames:

and then

#redefine FOO(a,b,c) "`~a'"

(I see similar macro tricks in some source code of compilers like gcc, so I think they are popular.)

jodavies commented 1 year ago

If it helps your code generation, you can also deal with extra commas in the list like:

#do i = {a,b,c,d,}
#ifdef `i'
   ....
#endif
#enddo
vermaseren commented 1 year ago

There is another way to do this when the file naes are also legal naes for symbols etc. CFunction f; AutoDeclare Symbol topo; Symbol x; L F = f(

include lib.h #topoNames

); ChainOut f; id f(x?) = x; .sort

do i = F

…….

enddo

As far as I can tell this should do the job.

On 11 Jun 2023, at 12:06, jodavies @.***> wrote:

If it helps your code generation, you can also deal with extra commas in the list like:

do i = {a,b,c,d,}

ifdef `i'

....

endif

enddo

— Reply to this email directly, view it on GitHub https://github.com/vermaseren/form/issues/448#issuecomment-1586099488, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABJPCETCJMJ7STVMOAJRQVLXKWKDNANCNFSM6AAAAAAZBVYPLM. You are receiving this because you are subscribed to this thread.

vermaseren commented 1 year ago

Little error in it. The Chainout should be Repeat id f(x1?,x2?,?a) = x1+f(x2,?a); id f(x?) = x; This way it is additive, rather than multiplicative. Sorry about that

On 11 Jun 2023, at 12:49, Jos Vermaseren @.***> wrote:

There is another way to do this when the file naes are also legal naes for symbols etc. CFunction f; AutoDeclare Symbol topo; Symbol x; L F = f(

include lib.h #topoNames

); ChainOut f; id f(x?) = x; .sort

do i = F

…….

enddo

As far as I can tell this should do the job.

On 11 Jun 2023, at 12:06, jodavies @.***> wrote:

If it helps your code generation, you can also deal with extra commas in the list like:

do i = {a,b,c,d,}

ifdef `i'

....

endif

enddo

— Reply to this email directly, view it on GitHub https://github.com/vermaseren/form/issues/448#issuecomment-1586099488, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABJPCETCJMJ7STVMOAJRQVLXKWKDNANCNFSM6AAAAAAZBVYPLM. You are receiving this because you are subscribed to this thread.

vsht commented 1 year ago

Thanks a lot for the numerous workarounds, I really appreciate it!

From my side the issue can be closed, unless there is need for more discussions regarding possible improvements in the future versions of FORM.