[GiNaC-devel] GiNaC is not a C compiler [Was: Optimized C-style output]

Sheplyakov Alexei varg at theor.jinr.ru
Wed Apr 4 11:53:14 CEST 2007


Dear Stefan,

On Tue, Apr 03, 2007 at 10:09:10AM +0200, Stefan Weinzierl wrote:
> after the discussions of the previous weeks comes now a new version for
> the code generation. There is now a new class "assign_lst",
> which has different methods for different things:

I don't think it is good idea. Each of these methods is useful on its
own...

>  replace_common_subex(flag) to replace common subexpressions. The flag can
>   used to select any combination from the set {add,mul,power,function} for
>   which one wants this substitution.

... this one in particular is generic enough and similar to already
exisitng collect_common_factors(), to_polynomial(), to_rational().
Please make it a separate function. Pretty *please*.

>  split_large_subex(nmax) splits subexpressions of type add or mul with
>   more than nmax operands.

The same here.

>  get_temporary_variables() returns the list of all new temporary variables
> 
>  print(ostream) and operator<<: Print it out.

> I attach an example program to show how it is used. The example program
> first prints for each example the standard csrc output and the modified
> (or "optimized") version.
> Examples 5 and 6 show some limitations.
> When running this program one gets:
> 
> Example 1: replace common subexpressions
>  double res = log(sin(y+x))+sin(y+x)+pow(sin(y+x),2.0)+log(y+x);
> 
>  double tmp1 = y+x;
>  double tmp0 = sin(tmp1);
>  double res = log(tmp0)+(tmp0*tmp0)+log(tmp1)+tmp0;

First of all, I'd prefer this to do the following:

ex e = log(sin(y+x))+sin(y+x)+pow(sin(y+x),2)+log(y+x);
exmap repls;
e = find_common_subex(e, repls);
// e:
// log(symbol0) + pow(symbol0, 2) + log(symbol1) + symbol0
// repls: symbol1 => y+x
//        symbol0 => sin(symbol1)

Such transformation is useful even if user is not going  to generate
any code at all.

Secondly, even for code generation this format is not flexible enough,
since it can produce only C/C++ code. In many languages variables has
to be declared in advance. That's why I insist on separate functions
for each task (finding common subexpressions, splitting large
subexpressions, printing the actual code).

> Example 2: as above, but don't replace add and mul
>  double res = log(sin(y+x))+sin(y+x)+pow(sin(y+x),2.0)+log(y+x);
> 
>  double tmp0 = sin(y+x);
>  double res = (tmp0*tmp0)+tmp0+log(tmp0)+log(y+x);
> 
> Example 3: works also on several assignments
>  double y1 = x2*sin(phi)+cos(phi)*x1;
>  double y2 = cos(phi)*x2-x1*sin(phi);
> 
>  double tmp1 = sin(phi);
>  double tmp0 = cos(phi);
>  double y1 = x1*tmp0+tmp1*x2;
>  double y2 = -x1*tmp1+tmp0*x2;
> 
> Example 4: split subexpressions with more than 6 operands
>  double res = x1+x0+y6*y1*y0*y5*y4*y9*y8*y3*y2*y7+x5+x4+x9+x8+x3+x2+x7+x6;

>  double tmp1 = x8+x3+x2+x7+x6;
>  double tmp3 = y8*y3*y2*y7;
>  double tmp2 = y6*y1*y0*y5*y4*y9;
>  double tmp0 = x1+x0+x5+x4+x9+tmp3*tmp2;
>  double res = tmp1+tmp0;

It would be much better in this form:

ex e = x1+x0+y6*y1*y0*y5*y4*y9*y8*y3*y2*y7+x5+x4+x9+x8+x3+x2+x7+x6;
size_t max_size = 6;
exmap repls;
e = split_large_subex(e, repls, max_size);
// e: symbol1 + symbol0
// repls: 
// tmp0 => x1+x0+x5+x4+x9+tmp3*tmp2
// tmp1 => x8+x3+x2+x7+x6
// tmp2 => y6*y1*y0*y5*y4*y9
// tmp3 => y8*y3*y2*y7

No need for get_temporary_variables() -- just iterate over repls.
But one need to sort entries so variables get defined before they
used.

> Example 5: pow(x+y,2) is not a subexpr of pow(x+y,4)
>  double res = 2.0*pow(y+x,2.0)+log(pow(y+x,4.0))+3.0*pow(y+x,3.0)+5.0*pow(y+x,5.0)+4.0*pow(y+x,4.0)+log(pow(y+x,2.0));
> 
>  double tmp2 = y+x;
>  double tmp1 = ((tmp2*tmp2)*(tmp2*tmp2));
>  double tmp0 = (tmp2*tmp2);
>  double res = log(tmp0)+log(tmp1)+5.0*(tmp2*(tmp2*tmp2)*(tmp2*tmp2))+3.0*(tmp2*tmp2*tmp2)+4.0*tmp1+2.0*tmp0;

So powers are always printed as products? I don't think it is nice,
would be better to allow user-defined formats, for instance, 
pow(tmp2, 5), or tmp2**5, or ... 

> Example 6: Substitution works only syntactically
>  double res = y+x+cos(y+x)+sin(y+x);
> 
>  double tmp0 = y+x;
>  double res = sin(tmp0)+y+x+cos(tmp0);

[snipped the code]

Best regards,
 Alexei
 
-- 
All science is either physics or stamp collecting.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
Url : http://www.cebix.net/pipermail/ginac-devel/attachments/20070404/cf9b080f/attachment.pgp


More information about the GiNaC-devel mailing list