Home | About | Partners | Contact Us
SourceForge Logo

Quick Links

Home
News
Thoughts and Rants
License
SourceForge Info
Download
Browse CVS
Mailing Lists

Thin Tools Examples...

Symbolic Differentiation
Constant folding
Execution Tracer
Contracts in Java
Removing useless code

Understanding...

Concept programming
Moka
XL
Thin Tools
Active Libraries
Refactoring
Optimizations
Coda
Notes

More Info

Contributors
Related Ideas
Some history
Applications
Other links
The GNU Project

Constant Folding Thin Tool

Concept programming relies on the creation of new abstractions for arbitrary concepts. In general, creating new abstraction comes with a significant loss in performance, something called the abstraction penalty.

Concept programming and thin tools offers the unique ability to create the application-specific optimizations to reduce the effects of the abstraction penalty. Because they are applications-specific, these optimizations can perform operations that would be unsafe in general.

The constantfold plug-in is an example of such application-specific optimization. It is designed in particular to simplify the output of the differentiation thin tool. The source code identifies operations that are useless byproducts of the differentiation process (like multiplying something by zero).

Simplifying Java Code

The plug-in can be invoked on a Java source code from Moka by using the +constantfold option:

% moka tests/example11.java +constantfold -out

The constant-folding plug-in recognizes the useless constructs (generated by the differentiation plug-in) in the following inefficient Java program:

// This example shows the symbolic differentiation "plugin"
class Test
{  
   
   
public static final double omega = 3.276
;
   public static final double theta = 0.227;
   public static final double decay = 0.001447;
   
   
public static int main(String[] args)
   {  
      
      // Tabulate the following expression
      
for(double t = 0t < 50t += 0.01)
      {  
         double y = 
         /**d(x*y)/dz->dx/dz*y+x*dy/dz**/
         /**dsin(x)/dx->cos(x)**/cos (2 * omega * t + theta) * (
            /**d(x+y)/dz->dx/dz+dy/dz**/
            /**d(x*y)/dz->dx/dz*y+x*dy/dz**/(
               /**d(x*y)/dz->dx/dz*y+x*dy/dz**/
               /**Integer Constant->0**/0 * omega + 2 * 
               /**dx/dy->0**/0) * t + 2 * omega * 
            /**dx/dx->1**/1 + 
            /**dx/dy->0**/0) * exp (-decay * t) + sin (2 * omega * t + theta) * (
            /**dexp(x)/dx->exp(x)**/exp (-decay * t) * (
               /**d(x*y)/dz->dx/dz*y+x*dy/dz**/-decay * t + -decay * 
               /**dx/dx->1**/1));
         System.out.println ("t=" + t + ", y=" + y);
      }
   }

}

The resulting simplified operations are shown below:

// This example shows the symbolic differentiation "plugin"
class Test
{  
   
   
public static final double omega = 3.276
;
   public static final double theta = 0.227;
   public static final double decay = 0.001447;
   
   
public static int main(String[] args)
   {  
      
      // Tabulate the following expression
      
for(double t = 0t < 50t += 0.01)
      {  
         double y = cos (2 * omega * t + theta) *
            (2 * omega) * exp (-(decay * t)) 
            + sin (2 * omega * t + theta) * -(exp (-(decay * t)) *
            (decay + decay * t));
         System.out.println ("t=" + t + ", y=" + y);
      }
   }

}

Application-specific optimizations in XL

The {constantfold} pragma can be used in XL. The particular class of optimization that it implements is already routinely done by compilers back-end, so it will not really improve performance in this particular case. However, it can be used to illustrate how application-specific optimizations can happen when the general semantics of the language would otherwise prevent them.

Consider the following XL code:

import IO = XL.UI.CONSOLE

function MulByZero(integer N) return integer written N * 0 is
    IO.WriteLn "Multiply by zero called"
    return 1

procedure Main is
    with integer Zero := {constantfold} 3 * 0
    IO.WriteLn "Zero=", Zero

    with integer One := 3 * 0
    IO.WriteLn "One=", One

The result of this program is:

Zero=0
Multiply by zero called
One=1

In the computation of Zero, the pragma ensures that the simplification 3*0 = 0 happens, regardless of the semantics of the language. It happens because of the semantics of the {constantfold} pragma, which apply before the XL semantics kick in. Thus, the result is 0. If the value 3 was replaced by a function call, the function would not even be called.

On the other hand, without the pragma, the language semantics require the function MulByZero to be called, thus the value of the variable One is one, and the message "Multiply by zero called" is emitted.


Copyright Christophe de Dinechin
First published Feb 17, 2000
Version 1.4 (updated 2004/01/20 06:16:14)