commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From l..@apache.org
Subject svn commit: r1408027 - in /commons/sandbox/nabla/trunk/src: main/java/org/apache/commons/nabla/forward/ main/java/org/apache/commons/nabla/forward/analysis/ main/java/org/apache/commons/nabla/forward/instructions/ test/java/org/apache/commons/nabla/for...
Date Sun, 11 Nov 2012 15:12:37 GMT
Author: luc
Date: Sun Nov 11 15:12:35 2012
New Revision: 1408027

URL: http://svn.apache.org/viewvc?rev=1408027&view=rev
Log:
Finalized work on fields differentiation.

Fields used to transfer data between various member functions are now
differentiated properly and the functions that use them are also
differentiated, even if they don't have any differentiable primitive
double parameters.

Modified:
    commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/DifferentiatedElementSpecification.java
    commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/ForwardModeDifferentiator.java
    commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/analysis/ClassDifferentiator.java
    commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/analysis/MethodDifferentiator.java
    commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/GetTransformer.java
    commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/InvokeNonMathTransformer.java
    commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/PutTransformer.java
    commons/sandbox/nabla/trunk/src/test/java/org/apache/commons/nabla/forward/ForwardModeDifferentiatorTest.java

Modified: commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/DifferentiatedElementSpecification.java
URL: http://svn.apache.org/viewvc/commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/DifferentiatedElementSpecification.java?rev=1408027&r1=1408026&r2=1408027&view=diff
==============================================================================
--- commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/DifferentiatedElementSpecification.java (original)
+++ commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/DifferentiatedElementSpecification.java Sun Nov 11 15:12:35 2012
@@ -30,16 +30,12 @@ public class DifferentiatedElementSpecif
     private final Type differentiatedType;
 
     /** Simple constructor.
-     * @param name element name
-     * @param isStatic if true, the element is static
-     * @param primitiveClass internal name of the class in which the element is defined
-     * @param primitiveType element type in the primitive
+     * @param primitiveSpec specification for the primitive element
      * @param differentiatedType element type in the differentiated class
      */
-    public DifferentiatedElementSpecification(final String name, final boolean isStatic,
-                                              final String primitiveClass, final Type primitiveType,
+    public DifferentiatedElementSpecification(final PrimitiveElementSpecification primitiveSpec,
                                               final Type differentiatedType) {
-        this.primitiveSpec      = new PrimitiveElementSpecification(name, isStatic, primitiveClass, primitiveType);
+        this.primitiveSpec      = primitiveSpec;
         this.differentiatedType = differentiatedType;
     }
 

Modified: commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/ForwardModeDifferentiator.java
URL: http://svn.apache.org/viewvc/commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/ForwardModeDifferentiator.java?rev=1408027&r1=1408026&r2=1408027&view=diff
==============================================================================
--- commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/ForwardModeDifferentiator.java (original)
+++ commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/ForwardModeDifferentiator.java Sun Nov 11 15:12:35 2012
@@ -64,6 +64,12 @@ public class ForwardModeDifferentiator i
     /** Suffix for differentiated classes. */
     private static final String CLASS_SUFFIX = "_NablaForwardModeDifferentiated";
 
+    /** Prefix for fields getters. */
+    private static final String GETTER_PREFIX = "get_Nabla_";
+
+    /** Prefix for fields setters. */
+    private static final String SETTER_PREFIX = "set_Nabla_";
+
     /** UnivariateFunction/UnivariateDifferentiableFunction map. */
     private final HashMap<Class<? extends UnivariateFunction>,
                           Class<? extends NablaUnivariateDifferentiableFunction>> map;
@@ -136,6 +142,22 @@ public class ForwardModeDifferentiator i
         return primitiveInternalName + CLASS_SUFFIX;
     }
 
+    /** Get the name of a field getter.
+     * @param name internal name of the field
+     * @return name of a getter for the field
+     */
+    public String getGetterName(final String name) {
+        return GETTER_PREFIX + name;
+    }
+
+    /** Get the name of a field setter.
+     * @param name internal name of the field
+     * @return name of a setter for the field
+     */
+    public String getSetterName(final String name) {
+        return SETTER_PREFIX + name;
+    }
+
     /** Check if a method uses a differentiated field.
      * @param method differentiable method to check
      * @return a differentiated field used by the method, null if it does not use any differentiated fields
@@ -169,28 +191,28 @@ public class ForwardModeDifferentiator i
  
     }
 
-    /** Get a differentiated method.
+    /** Check if a method is differentiated.
      * @param primitiveMethod primitive method specification to check
-     * @return a differentiated method corresponding to the primitive method, null if no methods correspond
+     * @return true if the method is differentiated
      */
-    public DifferentiatedElementSpecification getDifferentiatedMethod(final PrimitiveElementSpecification primitiveMethod) {
+    public boolean isDifferentiatedMethod(final PrimitiveElementSpecification primitiveMethod) {
 
         // loop over all pending methods
         for (final DifferentiatedElementSpecification method : pendingMethods) {
             if (method.getPrimitiveSpec().equals(primitiveMethod)) {
-                return method;
+                return true;
             }
         }
 
         // loop over all processed methods
         for (final DifferentiatedElementSpecification method : processedMethods) {
             if (method.getPrimitiveSpec().equals(primitiveMethod)) {
-                return method;
+                return true;
             }
         }
 
         // none of the methods we are interested in correspond to the specification
-        return null;
+        return false;
  
     }
 
@@ -221,28 +243,28 @@ public class ForwardModeDifferentiator i
         }
     }
 
-    /** Get a differentiated field.
+    /** Check if a field is differentiated.
      * @param primitiveField primitive field specification to check
-     * @return a differentiated field corresponding to the primitive field, null if no fields correspond
+     * @return true if the field is differentiated
      */
-    public DifferentiatedElementSpecification getDifferentiatedField(final PrimitiveElementSpecification primitiveField) {
+    public boolean isDifferentiatedField(final PrimitiveElementSpecification primitiveField) {
 
         // loop over all pending fields
         for (final DifferentiatedElementSpecification field : pendingFields) {
             if (field.getPrimitiveSpec().equals(primitiveField)) {
-                return field;
+                return true;
             }
         }
 
         // loop over all processed fields
         for (final DifferentiatedElementSpecification field : processedFields) {
             if (field.getPrimitiveSpec().equals(primitiveField)) {
-                return field;
+                return true;
             }
         }
 
         // none of the fields we are interested in correspond to the specification
-        return null;
+        return false;
  
     }
 
@@ -276,20 +298,29 @@ public class ForwardModeDifferentiator i
 
     }
 
-    /** Check if a type is a double or a double array with any dimension.
+    /** Check if a type is expected to be transformed.
+     * <p>
+     * If the original type is one we want to transform (like double our double arrays
+     * with various dimensions), return true. Otherwise, return false.
+     * </p>
      * @param type type to check
-     * @return true if the type is a double type or a double array type with any dimension
+     * @return true if the type is expected to be transformed
      */
-    public boolean isDoubleOrDoubleArray(final Type type) {
+    public boolean isTransformableType(final Type type) {
         return type.equals(Type.DOUBLE_TYPE) ||
                 (type.getSort() == Type.ARRAY && type.getElementType().equals(Type.DOUBLE_TYPE));
     }
 
-    /** Convert a double or a double array type to the corresponding {@link DerivativeStructure} type.
+    /** Convert an original type to the corresponding transformed type.
+     * <p>
+     * If the original type is one we want to transform (like double our double arrays
+     * with various dimensions), it will be converted. Otherwise, the argument itself
+     * will be returned.
+     * </p>
      * @param type type to convert
      * @return converted type
      */
-    public Type convertDoubleOrDoubleArray(final Type type) {
+    public Type transformType(final Type type) {
         final Type dsType = Type.getType(DerivativeStructure.class);
         if (type.equals(Type.DOUBLE_TYPE)) {
             return dsType;
@@ -360,11 +391,15 @@ public class ForwardModeDifferentiator i
         throws DifferentiationException {
 
         // bootstrap differentiation starting from the top level value function defined by the UnivariateFunction interface
-        requestMethodDifferentiation(new DifferentiatedElementSpecification("value", false,
-                                     Type.getInternalName(differentiableClass),
-                                     Type.getMethodType(Type.DOUBLE_TYPE, Type.DOUBLE_TYPE),
-                                     Type.getMethodType(convertDoubleOrDoubleArray(Type.DOUBLE_TYPE),
-                                                        convertDoubleOrDoubleArray(Type.DOUBLE_TYPE))));
+        final PrimitiveElementSpecification primitiveValueMethod =
+                new PrimitiveElementSpecification("value", false,
+                                                  Type.getInternalName(differentiableClass),
+                                                  Type.getMethodType(Type.DOUBLE_TYPE, Type.DOUBLE_TYPE));
+        final DifferentiatedElementSpecification differentiatedValueMethod =
+                new DifferentiatedElementSpecification(primitiveValueMethod,
+                                                       Type.getMethodType(transformType(Type.DOUBLE_TYPE),
+                                                                          transformType(Type.DOUBLE_TYPE)));
+        requestMethodDifferentiation(differentiatedValueMethod);
 
         // loop while there is still something to differentiate (either fields or methods)
         while (!(pendingFields.isEmpty() && pendingMethods.isEmpty())) {
@@ -380,14 +415,14 @@ public class ForwardModeDifferentiator i
 
             // differentiate the fields
             for (final DifferentiatedElementSpecification field : fields) {
-                getDifferentiator(field.getPrimitiveSpec()).differentiateField(field);
                 processedFields.add(field);
+                getDifferentiator(field.getPrimitiveSpec()).differentiateField(field);
             }
 
             // differentiate the methods
             for (final DifferentiatedElementSpecification method : methods) {
-                getDifferentiator(method.getPrimitiveSpec()).differentiateMethod(method);
                 processedMethods.add(method);
+                getDifferentiator(method.getPrimitiveSpec()).differentiateMethod(method);
             }
 
         }

Modified: commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/analysis/ClassDifferentiator.java
URL: http://svn.apache.org/viewvc/commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/analysis/ClassDifferentiator.java?rev=1408027&r1=1408026&r2=1408027&view=diff
==============================================================================
--- commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/analysis/ClassDifferentiator.java (original)
+++ commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/analysis/ClassDifferentiator.java Sun Nov 11 15:12:35 2012
@@ -59,9 +59,6 @@ public class ClassDifferentiator {
     /** Name fo the constructor methods. */
     private static final String INIT = "<init>";
 
-    /** Prefix for fields getters. */
-    private static final String GETTER_PREFIX = "get_Nabla_";
-
     /** Math implementation classes. */
     private final Set<String> mathClasses;
 
@@ -195,31 +192,38 @@ public class ClassDifferentiator {
                 final MethodDifferentiator differentiator = new MethodDifferentiator(mathClasses, this);
                 final MethodNode differentiatedNode =
                         differentiator.differentiate(primitiveMethod, differentiatedMethod);
-                classNode.methods.add(differentiatedNode);
+                storeDifferentiatedMethode(differentiatedNode);
                 return;
             }
         }
 
     }
 
-    /** Clear a differentiated method.
+    /** Overwrite a differentiated method.
      * <p>
-     * Clearing a differentiated method is used mainly when it uses a field
-     * that was once thought to not be affected by differentiation but
-     * afterwards appear to be differentiated too. So the method access to the
-     * now differentiated field needs to be updated by differentiating the
-     * method again taking the proper information into account.
+     * Methods may be differentiated several time as some of their dependencies
+     * (fields or other methods) may be appear to need differentiation too
+     * after the method has already been differentiated. This method overwrites
+     * eventual prior differentiation attempts with a new differentiation, so
+     * there are no duplicate in the class (methods with same name and same
+     * signature). So this method can be called several time, each call overwriting
+     * the previous one up to the time the class bytecode is generated.
      * </p>
-     * @param method differentiated method to clear
+     * @param method new differentiated method
      */
-    public void clearDifferentiatedElement(final DifferentiatedElementSpecification method) {
+    private void storeDifferentiatedMethode(final MethodNode method) {
+
+        // remove prior differentiations for the same method
         for (final Iterator<MethodNode> iterator = classNode.methods.iterator(); iterator.hasNext();) {
             final MethodNode current = iterator.next();
-            if (current.name.equals(method.getPrimitiveSpec().getName()) &&
-                Type.getMethodType(current.desc).equals(method.getDifferentiatedType())) {
+            if (current.name.equals(method.name) && current.desc.equals(method.desc)) {
                 iterator.remove();
             }
         }
+
+        // store new differentiation
+        classNode.methods.add(method);
+
     }
 
     /** Get all methods that call a method.
@@ -291,7 +295,8 @@ public class ClassDifferentiator {
         throws DifferentiationException {
 
         // set up the field itself
-        classNode.fields.add(new FieldNode(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL,
+        classNode.fields.add(new FieldNode(Opcodes.ACC_PRIVATE |
+                                           (differentiableField.getPrimitiveSpec().isStatic() ? Opcodes.ACC_STATIC: 0),
                                            differentiableField.getPrimitiveSpec().getName(),
                                            differentiableField.getDifferentiatedType().getDescriptor(),
                                            null, null));
@@ -304,32 +309,70 @@ public class ClassDifferentiator {
             }
         }
 
-        // set up a private getter for the field
-        // the following bytecode is equivalent to the following java code
-        //    public/protected/private DerivativeStructure get_x(int parameters, int order) {
-        //        if (x == null) {
-        //            x = new DerivativeStructure(parameters, order,
-        //                                        ((Double) getPrimitiveField("x")).doubleValue());
-        //        }
-        //        return x;
-        //    }
-        final Type transformedType = convertDoubleOrDoubleArray(Type.DOUBLE_TYPE);
+        if (differentiableField.getPrimitiveSpec().isStatic()) {
+            classNode.methods.add(createStaticGetter(access,
+                                                     differentiableField.getPrimitiveSpec().getName(),
+                                                     differentiableField.getDifferentiatedType().getDescriptor(),
+                                                     differentiableField.getPrimitiveSpec().getPrimitiveClass()));
+            classNode.methods.add(createStaticSetter(access,
+                                                     differentiableField.getPrimitiveSpec().getName(),
+                                                     differentiableField.getDifferentiatedType().getDescriptor(),
+                                                     differentiableField.getPrimitiveSpec().getPrimitiveClass()));
+        } else {
+            classNode.methods.add(createGetter(access,
+                                               differentiableField.getPrimitiveSpec().getName(),
+                                               differentiableField.getDifferentiatedType().getDescriptor()));
+            classNode.methods.add(createSetter(access,
+                                               differentiableField.getPrimitiveSpec().getName(),
+                                               differentiableField.getDifferentiatedType().getDescriptor()));
+        }
+    }
+
+    /** Get the name of a field getter.
+     * @param name internal name of the field
+     * @return name of a getter for the field
+     */
+    public String getGetterName(final String name) {
+        return forwardDifferentiator.getGetterName(name);
+    }
+
+    /** Get the name of a field setter.
+     * @param name internal name of the field
+     * @return name of a setter for the field
+     */
+    public String getSetterName(final String name) {
+        return forwardDifferentiator.getSetterName(name);
+    }
+
+    /** Set up a getter for a field
+     * <p>
+     * The following bytecode is equivalent to the following java code:
+     * </p>
+     * <code>
+     *    public/protected/private DerivativeStructure get_x(int parameters, int order) {
+     *        if (x == null) {
+     *            x = new DerivativeStructure(parameters, order,
+     *                                        ((Double) getPrimitiveField("x")).doubleValue());
+     *        }
+     *        return x;
+     *    }
+     * </code>
+     * @param access access flag for the field
+     * @param name name of the field
+     * @param desc descriptor of the transformed field
+     * @return a method node for the getter
+     */
+    private MethodNode createGetter(final int access, final String name, final String desc) {
+
+        final Type transformedType = Type.getType(desc);
         final MethodNode getter =
-                new MethodNode(access | Opcodes.ACC_SYNTHETIC,
-                               GETTER_PREFIX + differentiableField.getPrimitiveSpec().getName(),
+                new MethodNode(access | Opcodes.ACC_SYNTHETIC, getGetterName(name),
                                Type.getMethodDescriptor(transformedType,
                                                         Type.INT_TYPE, Type.INT_TYPE),
-                               null, null);
+                                                        null, null);
         getter.visitVarInsn(Opcodes.ALOAD, 0);
-        if (differentiableField.getPrimitiveSpec().isStatic()) {
-            getter.visitFieldInsn(Opcodes.GETSTATIC, getDifferentiatedInternalName(getPrimitiveInternalName()),
-                                  differentiableField.getPrimitiveSpec().getName(),
-                                  differentiableField.getDifferentiatedType().getDescriptor());
-        } else {
-            getter.visitFieldInsn(Opcodes.GETFIELD, getDifferentiatedInternalName(getPrimitiveInternalName()),
-                                  differentiableField.getPrimitiveSpec().getName(),
-                                  differentiableField.getDifferentiatedType().getDescriptor());
-        }
+        getter.visitFieldInsn(Opcodes.GETFIELD, getDifferentiatedInternalName(getPrimitiveInternalName()),
+                              name, desc);
         Label ifNonNull = new Label();
         getter.visitJumpInsn(Opcodes.IFNONNULL, ifNonNull);
         getter.visitVarInsn(Opcodes.ALOAD, 0);
@@ -338,7 +381,7 @@ public class ClassDifferentiator {
         getter.visitVarInsn(Opcodes.ILOAD, 1);
         getter.visitVarInsn(Opcodes.ILOAD, 2);
         getter.visitVarInsn(Opcodes.ALOAD, 0);
-        getter.visitLdcInsn(differentiableField.getPrimitiveSpec().getName());
+        getter.visitLdcInsn(name);
         getter.visitMethodInsn(Opcodes.INVOKEVIRTUAL, getDifferentiatedInternalName(getPrimitiveInternalName()),
                                "getPrimitiveField", Type.getMethodDescriptor(Type.getType(Object.class),
                                                                              Type.getType(String.class)));
@@ -348,31 +391,175 @@ public class ClassDifferentiator {
                                Type.getMethodDescriptor(Type.DOUBLE_TYPE));
         getter.visitMethodInsn(Opcodes.INVOKESPECIAL, transformedType.getInternalName(), INIT,
                                Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE, Type.INT_TYPE, Type.DOUBLE_TYPE));
-
-        if (differentiableField.getPrimitiveSpec().isStatic()) {
-            getter.visitFieldInsn(Opcodes.PUTSTATIC, getDifferentiatedInternalName(getPrimitiveInternalName()),
-                                  differentiableField.getPrimitiveSpec().getName(),
-                                  transformedType.getDescriptor());
-        } else {
-            getter.visitFieldInsn(Opcodes.PUTFIELD, getDifferentiatedInternalName(getPrimitiveInternalName()),
-                                  differentiableField.getPrimitiveSpec().getName(),
-                                  transformedType.getDescriptor());
-        }
+        getter.visitFieldInsn(Opcodes.PUTFIELD, getDifferentiatedInternalName(getPrimitiveInternalName()),
+                              name, transformedType.getDescriptor());
 
         getter.visitLabel(ifNonNull);
 
         getter.visitVarInsn(Opcodes.ALOAD, 0);
-        if (differentiableField.getPrimitiveSpec().isStatic()) {
-            getter.visitFieldInsn(Opcodes.GETSTATIC, classNode.name, differentiableField.getPrimitiveSpec().getName(),
-                                  transformedType.getDescriptor());
-        } else {
-            getter.visitFieldInsn(Opcodes.GETFIELD, classNode.name, differentiableField.getPrimitiveSpec().getName(),
-                                  transformedType.getDescriptor());
-        }
+        getter.visitFieldInsn(Opcodes.GETFIELD, classNode.name, name,
+                              transformedType.getDescriptor());
 
         getter.visitInsn(Opcodes.ARETURN);
         getter.visitMaxs(7, 3);
-        classNode.methods.add(getter);
+
+        return getter;
+
+    }
+
+    /** Set up a setter for a field
+     * <p>
+     * The following bytecode is equivalent to the following java code:
+     * </p>
+     * <code>
+     *    public/protected/private void set_x(DerivativeStructure a) {
+     *        x = a;
+     *        putPrimitiveStaticField(Double.valueOf(a.getValue()), Primitive.class, "x");
+     *    }
+     * </code>
+     * @param access access flag for the field
+     * @param name name of the field
+     * @param desc descriptor of the transformed field
+     * @return a method node for the setter
+     */
+    private MethodNode createSetter(final int access, final String name, final String desc) {
+
+        final Type transformedType = Type.getType(desc);
+        final MethodNode setter =
+                new MethodNode(access | Opcodes.ACC_SYNTHETIC, getSetterName(name),
+                               Type.getMethodDescriptor(Type.VOID_TYPE, transformedType),
+                               null, null);
+
+        setter.visitVarInsn(Opcodes.ALOAD, 0);
+        setter.visitVarInsn(Opcodes.ALOAD, 1);
+        setter.visitFieldInsn(Opcodes.PUTFIELD, getDifferentiatedInternalName(getPrimitiveInternalName()),
+                              name, desc);
+        setter.visitVarInsn(Opcodes.ALOAD, 0);
+        setter.visitVarInsn(Opcodes.ALOAD, 1);
+        setter.visitMethodInsn(Opcodes.INVOKEVIRTUAL, transformedType.getInternalName(),
+                               "getValue", Type.getMethodDescriptor(Type.DOUBLE_TYPE));
+        final Type doubleType = Type.getType(Double.class);
+        setter.visitMethodInsn(Opcodes.INVOKESTATIC, doubleType.getInternalName(), "valueOf",
+                               Type.getMethodDescriptor(doubleType, Type.DOUBLE_TYPE));
+        setter.visitLdcInsn(name);
+        setter.visitMethodInsn(Opcodes.INVOKEVIRTUAL, getDifferentiatedInternalName(getPrimitiveInternalName()),
+                               "putPrimitiveField", Type.getMethodDescriptor(Type.VOID_TYPE,
+                                                                             Type.getType(Object.class),
+                                                                             Type.getType(String.class)));
+        setter.visitInsn(Opcodes.RETURN);
+        setter.visitMaxs(3, 2);
+
+        return setter;
+
+    }
+
+    /** Set up a static getter for a static field
+     * <p>
+     * The following bytecode is equivalent to the following java code:
+     * </p>
+     * <code>
+     *    public/protected/private static DerivativeStructure get_x(int parameters, int order) {
+     *        if (x == null) {
+     *            x = new DerivativeStructure(parameters, order,
+     *                                        ((Double) getPrimitiveStaticField(Primitive.class, "x")).doubleValue());
+     *        }
+     *        return x;
+     *    }
+     * </code>
+     * @param access access flag for the field
+     * @param name name of the field
+     * @param desc descriptor of the transformed field
+     * @param primitiveClass type of the primitive class
+     * @return a method node for the static getter
+     */
+    private MethodNode createStaticGetter(final int access, final String name, final String desc, final String primitiveClass) {
+
+        final Type transformedType = Type.getType(desc);
+        final MethodNode getter =
+                new MethodNode(access | Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC,
+                               getGetterName(name),
+                               Type.getMethodDescriptor(transformedType, Type.INT_TYPE, Type.INT_TYPE),
+                               null, null);
+
+        getter.visitFieldInsn(Opcodes.GETSTATIC, getDifferentiatedInternalName(getPrimitiveInternalName()),
+                              name, desc);
+        Label ifNonNull = new Label();
+        getter.visitJumpInsn(Opcodes.IFNONNULL, ifNonNull);
+        getter.visitTypeInsn(Opcodes.NEW, transformedType.getInternalName());
+        getter.visitInsn(Opcodes.DUP);
+        getter.visitVarInsn(Opcodes.ILOAD, 0);
+        getter.visitVarInsn(Opcodes.ILOAD, 1);
+        getter.visitLdcInsn(Type.getType("L" + primitiveClass + ";"));
+        getter.visitLdcInsn(name);
+        getter.visitMethodInsn(Opcodes.INVOKESTATIC, getDifferentiatedInternalName(getPrimitiveInternalName()),
+                               "getPrimitiveStaticField",
+                               Type.getMethodDescriptor(Type.getType(Object.class),
+                                                        Type.getType(Class.class),
+                                                        Type.getType(String.class)));
+        final Type doubleType = Type.getType(Double.class);
+        getter.visitTypeInsn(Opcodes.CHECKCAST, doubleType.getInternalName());
+        getter.visitMethodInsn(Opcodes.INVOKEVIRTUAL, doubleType.getInternalName(), "doubleValue",
+                               Type.getMethodDescriptor(Type.DOUBLE_TYPE));
+        getter.visitMethodInsn(Opcodes.INVOKESPECIAL, transformedType.getInternalName(), INIT,
+                               Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE, Type.INT_TYPE, Type.DOUBLE_TYPE));
+
+        getter.visitFieldInsn(Opcodes.PUTSTATIC, getDifferentiatedInternalName(getPrimitiveInternalName()),
+                              name, transformedType.getDescriptor());
+
+        getter.visitLabel(ifNonNull);
+
+        getter.visitFieldInsn(Opcodes.GETSTATIC, classNode.name, name,
+                              transformedType.getDescriptor());
+
+        getter.visitInsn(Opcodes.ARETURN);
+        getter.visitMaxs(6, 2);
+        return getter;
+
+    }
+
+    /** Set up a static setter for a static field
+     * <p>
+     * The following bytecode is equivalent to the following java code:
+     * </p>
+     * <code>
+     *    public/protected/private static void set_x(DerivativeStructure a) {
+     *        x = a;putPrimitiveStaticField(Double.valueOf(a.getValue()), Primitive.class, "x");
+     *    }
+     * </code>
+     * @param access access flag for the field
+     * @param name name of the field
+     * @param desc descriptor of the transformed field
+     * @param primitiveClass type of the primitive class
+     * @return a method node for the setter
+     */
+    private MethodNode createStaticSetter(final int access, final String name, final String desc, final String primitiveClass) {
+
+        final Type transformedType = Type.getType(desc);
+        final MethodNode setter =
+                new MethodNode(access | Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC, getSetterName(name),
+                               Type.getMethodDescriptor(Type.VOID_TYPE, transformedType),
+                               null, null);
+
+        setter.visitVarInsn(Opcodes.ALOAD, 0);
+        setter.visitFieldInsn(Opcodes.PUTSTATIC, getDifferentiatedInternalName(getPrimitiveInternalName()),
+                              name, desc);
+        setter.visitVarInsn(Opcodes.ALOAD, 0);
+        setter.visitMethodInsn(Opcodes.INVOKEVIRTUAL, transformedType.getInternalName(),
+                               "getValue", Type.getMethodDescriptor(Type.DOUBLE_TYPE));
+        final Type doubleType = Type.getType(Double.class);
+        setter.visitMethodInsn(Opcodes.INVOKESTATIC, doubleType.getInternalName(), "valueOf",
+                               Type.getMethodDescriptor(doubleType, Type.DOUBLE_TYPE));
+        setter.visitLdcInsn(Type.getType("L" + primitiveClass + ";"));
+        setter.visitLdcInsn(name);
+        setter.visitMethodInsn(Opcodes.INVOKESTATIC, getDifferentiatedInternalName(getPrimitiveInternalName()),
+                               "putPrimitiveStaticField", Type.getMethodDescriptor(Type.VOID_TYPE,
+                                                                                   Type.getType(Object.class),
+                                                                                   Type.getType(Class.class),
+                                                                                   Type.getType(String.class)));
+        setter.visitInsn(Opcodes.RETURN);
+        setter.visitMaxs(3, 1);
+
+        return setter;
 
     }
 
@@ -392,12 +579,12 @@ public class ClassDifferentiator {
         return forwardDifferentiator.getUsedDifferentiatedField(method);
     }
 
-    /** Get a differentiated method.
+    /** Check if a method is differentiated.
      * @param primitiveMethod primitive method specification to check
-     * @return a differentiated method corresponding to the primitive method, null if no methods correspond
+     * @return true if the method is differentiated
      */
-    public DifferentiatedElementSpecification getDifferentiatedMethod(final PrimitiveElementSpecification primitiveMethod) {
-        return forwardDifferentiator.getDifferentiatedMethod(primitiveMethod);
+    public boolean isDifferentiatedMethod(final PrimitiveElementSpecification primitiveMethod) {
+        return forwardDifferentiator.isDifferentiatedMethod(primitiveMethod);
     }
 
     /** Request differentiation of a method.
@@ -407,12 +594,12 @@ public class ClassDifferentiator {
         forwardDifferentiator.requestMethodDifferentiation(method);
     }
 
-    /** Get a differentiated field.
+    /** Check if a field is differentiated.
      * @param primitiveField primitive field specification to check
-     * @return a differentiated field corresponding to the primitive field, null if no fields correspond
+     * @return true if the field is differentiated
      */
-    public DifferentiatedElementSpecification getDifferentiatedField(final PrimitiveElementSpecification primitiveField) {
-        return forwardDifferentiator.getDifferentiatedField(primitiveField);
+    public boolean isDifferentiatedField(final PrimitiveElementSpecification primitiveField) {
+        return forwardDifferentiator.isDifferentiatedField(primitiveField);
     }
 
     /** Request differentiation of a field.
@@ -422,20 +609,29 @@ public class ClassDifferentiator {
         forwardDifferentiator.requestFieldDifferentiation(field);
     }
 
-    /** Check if a type is a double or a double array with any dimension.
+    /** Check if a type is expected to be transformed.
+     * <p>
+     * If the original type is one we want to transform (like double our double arrays
+     * with various dimensions), return true. Otherwise, return false.
+     * </p>
      * @param type type to check
-     * @return true if the type is a double type or a double array type with any dimension
+     * @return true if the type is expected to be transformed
      */
-    public boolean isDoubleOrDoubleArray(final Type type) {
-        return forwardDifferentiator.isDoubleOrDoubleArray(type);
+    public boolean isTransformableType(final Type type) {
+        return forwardDifferentiator.isTransformableType(type);
     }
 
-    /** Convert a double or a double array type to the corresponding transformed type.
+    /** Convert an original type to the corresponding transformed type.
+     * <p>
+     * If the original type is one we want to transform (like double our double arrays
+     * with various dimensions), it will be converted. Otherwise, the argument itself
+     * will be returned.
+     * </p>
      * @param type type to convert
      * @return converted type
      */
-    public Type convertDoubleOrDoubleArray(final Type type) {
-        return forwardDifferentiator.convertDoubleOrDoubleArray(type);
+    public Type transformType(final Type type) {
+        return forwardDifferentiator.transformType(type);
     }
 
 }

Modified: commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/analysis/MethodDifferentiator.java
URL: http://svn.apache.org/viewvc/commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/analysis/MethodDifferentiator.java?rev=1408027&r1=1408026&r2=1408027&view=diff
==============================================================================
--- commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/analysis/MethodDifferentiator.java (original)
+++ commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/analysis/MethodDifferentiator.java Sun Nov 11 15:12:35 2012
@@ -109,6 +109,22 @@ public class MethodDifferentiator {
         return classDifferentiator.getPrimitiveInternalName();
     }
 
+    /** Get the name of a field getter.
+     * @param name internal name of the field
+     * @return name of a getter for the field
+     */
+    public String getGetterName(final String name) {
+        return classDifferentiator.getGetterName(name);
+    }
+
+    /** Get the name of a field setter.
+     * @param name internal name of the field
+     * @return name of a setter for the field
+     */
+    public String getSetterName(final String name) {
+        return classDifferentiator.getSetterName(name);
+    }
+
     /**
      * Differentiate a method.
      * @param primitiveMethod method to differentiate
@@ -254,96 +270,66 @@ public class MethodDifferentiator {
     }
 
     /** Check if a method uses a differentiated field.
-     * @param method method name
-     * @param isStatic if true, the method is static
-     * @param owner class in which the method is defined
-     * @param primitiveMethodType method type in the primitive (includes return and arguments types)
+     * @param primitiveMethod primitive method specification to check
      * @return a differentiated field used by the method, null if it does not use any differentiated fields
      */
-    public DifferentiatedElementSpecification getUsedDifferentiatedField(final String method,
-                                                                         final boolean isStatic,
-                                                                         final String owner,
-                                                                         final Type primitiveMethodType) {
-        final PrimitiveElementSpecification dm =
-                new PrimitiveElementSpecification(method, isStatic, owner, primitiveMethodType);
-        return classDifferentiator.getUsedDifferentiatedField(dm);
+    public DifferentiatedElementSpecification getUsedDifferentiatedField(final PrimitiveElementSpecification primitiveMethod) {
+        return classDifferentiator.getUsedDifferentiatedField(primitiveMethod);
     }
 
-    /** Get a differentiated method.
-     * @param method method name
-     * @param isStatic if true, the method is static
-     * @param owner class in which the method is defined
-     * @param primitiveType method type in the primitive
-     * @return a differentiated method corresponding to the primitive method, null if no methods correspond
-     */
-    public DifferentiatedElementSpecification getDifferentiatedMethod(final String method, final boolean isStatic,
-                                                                      final String owner, final Type primitiveType) {
-        final PrimitiveElementSpecification primitiveMethod =
-                new PrimitiveElementSpecification(method, isStatic, owner, primitiveType);
-        return classDifferentiator.getDifferentiatedMethod(primitiveMethod);
+    /** Check if a method is differentiated.
+     * @param primitiveMethod primitive method specification to check
+     * @return true if the method is differentiated
+     */
+    public boolean isDifferentiatedMethod(final PrimitiveElementSpecification primitiveMethod) {
+        return classDifferentiator.isDifferentiatedMethod(primitiveMethod);
     }
 
     /** Request differentiation of a method.
-     * @param method method name
-     * @param isStatic if true, the method is static
-     * @param owner class in which the method is defined
-     * @param primitiveMethodType method type in the primitive (includes return and arguments types)
-     * @param differentiatedMethodType method type in the differentiated class (includes return and arguments types)
-     */
-    public void requestMethodDifferentiation(final String method, final boolean isStatic,
-                                             final String owner, final Type primitiveMethodType,
-                                             final Type differentiatedMethodType) {
-            final DifferentiatedElementSpecification dm =
-                    new DifferentiatedElementSpecification(method, isStatic, owner,
-                                              primitiveMethodType, differentiatedMethodType);
-            classDifferentiator.requestMethodDifferentiation(dm);
-    }
-
-    /** Get a differentiated field.
-     * @param field field name
-     * @param isStatic if true, the field is static
-     * @param owner class in which the field is defined
-     * @param primitiveType field type in the primitive
-     * @return a differentiated field corresponding to the primitive field, null if no fields correspond
-     */
-    public DifferentiatedElementSpecification getDifferentiatedField(final String field, final boolean isStatic,
-                                                                     final String owner, final Type primitiveType) {
-        final PrimitiveElementSpecification primitiveField =
-                new PrimitiveElementSpecification(field, isStatic, owner, primitiveType);
-        return classDifferentiator.getDifferentiatedField(primitiveField);
+     * @param method method to differentiate
+     */
+    public void requestMethodDifferentiation(final DifferentiatedElementSpecification method) {
+        classDifferentiator.requestMethodDifferentiation(method);
+    }
+
+    /** Check if a field is differentiated.
+     * @param primitiveField primitive field specification to check
+     * @return true if the field is differentiated
+     */
+    public boolean isDifferentiatedField(final PrimitiveElementSpecification primitiveField) {
+        return classDifferentiator.isDifferentiatedField(primitiveField);
     }
 
     /** Request differentiation of a field.
-     * @param field field name
-     * @param isStatic if true, the field is static
-     * @param owner class in which the field is defined
-     * @param primitiveFieldType field type in the primitive
-     * @param differentiatedFieldType field type in the differentiated class
-     */
-    public void requestFieldDifferentiation(final String field, final boolean isStatic,
-                                            final String owner, final Type primitiveFieldType,
-                                            final Type differentiatedFieldType) {
-            final DifferentiatedElementSpecification df =
-                    new DifferentiatedElementSpecification(field, isStatic,
-                                                           owner, primitiveFieldType,
-                                                           differentiatedFieldType);
-            classDifferentiator.requestFieldDifferentiation(df);
+     * @param field field to differentiate
+     */
+    public void requestFieldDifferentiation(final DifferentiatedElementSpecification field) {
+        classDifferentiator.requestFieldDifferentiation(field);
     }
 
-    /** Check if a type is a double or a double array with any dimension.
+    /** Check if a type is expected to be transformed.
+     * <p>
+     * If the original type is one we want to transform (like double our double arrays
+     * with various dimensions), return true. Otherwise, return false.
+     * </p>
      * @param type type to check
-     * @return true if the type is a double type or a double array type with any dimension
+     * @return true if the type is expected to be transformed
      */
-    public boolean isDoubleOrDoubleArray(final Type type) {
-        return classDifferentiator.isDoubleOrDoubleArray(type);
+    public boolean isTransformableType(final Type type) {
+        return classDifferentiator.isTransformableType(type);
     }
 
-    /** Convert a double or a double array type to the corresponding transformed type.
+    /** Convert an original type to the corresponding transformed type.
+     * <p>
+     * If the original type is one we want to transform (like double our double arrays
+     * with various dimensions), it will be converted. Otherwise, the argument itself
+     * will be returned.
+     * </p>
      * @param type type to convert
      * @return converted type
      */
-    public Type convertDoubleOrDoubleArray(final Type type) {
-        return classDifferentiator.convertDoubleOrDoubleArray(type);
+    public Type transformType(final Type type) {
+        return classDifferentiator.transformType(type);
     }
 
     /** Identify the instructions that must be changed.
@@ -435,8 +421,10 @@ public class MethodDifferentiator {
                 changes.add(insn);
             } else if (insn.getType() == AbstractInsnNode.METHOD_INSN) {
                 final MethodInsnNode methodInsn = (MethodInsnNode) insn;
-                if (getUsedDifferentiatedField(methodInsn.name, insn.getOpcode() == Opcodes.INVOKESTATIC,
-                                               methodInsn.owner, Type.getMethodType(methodInsn.desc)) != null) {
+                final PrimitiveElementSpecification primitiveMethod =
+                        new PrimitiveElementSpecification(methodInsn.name, insn.getOpcode() == Opcodes.INVOKESTATIC,
+                                                          methodInsn.owner, Type.getMethodType(methodInsn.desc));
+                if (getUsedDifferentiatedField(primitiveMethod) != null) {
                     // the invoke instructions on methods that use differentiated fields must be changed
                     changes.add(insn);
                 }
@@ -479,7 +467,6 @@ public class MethodDifferentiator {
                 changedValues.add(initialFrame.getLocal(index));
 
                 // the second half of this argument local variable will disappear
-                // TODO: should Nabla support such arguments override?
                 for (ListIterator<AbstractInsnNode> iterator = instructions.iterator(); iterator.hasNext();) {
                     final AbstractInsnNode insn = iterator.next();
                     if (insn.getType() == AbstractInsnNode.VAR_INSN) {
@@ -492,11 +479,13 @@ public class MethodDifferentiator {
                             } else {
                                 // the argument is overridden by some other variable type
                                 // for now we don't know how to handle this case
+                                // TODO: should Nabla support such arguments override?
                                 throw DifferentiationException.createInternalError(null);
                             }
                         } else if (var == index + 1) {
                             // the second half of the argument is overridden by some other variable type
                             // for now we don't know how to handle this case
+                            // TODO: should Nabla support such arguments override?
                             throw DifferentiationException.createInternalError(null); 
                         }
                     } else if (insn.getType() == AbstractInsnNode.IINC_INSN) {
@@ -504,6 +493,7 @@ public class MethodDifferentiator {
                         if (var == index || var == index + 1) {
                             // the argument is overridden by some other variable type
                             // for now we don't know how to handle this case
+                            // TODO: should Nabla support such arguments override?
                             throw DifferentiationException.createInternalError(null); 
                         }
                     }
@@ -545,13 +535,14 @@ public class MethodDifferentiator {
             final AbstractInsnNode insn = iterator.next();
             if (insn.getType() == AbstractInsnNode.METHOD_INSN) {
                 final MethodInsnNode methodInsn = (MethodInsnNode) insn;
-                final DifferentiatedElementSpecification de =
-                        getDifferentiatedMethod(methodInsn.name, methodInsn.getOpcode() == Opcodes.INVOKESTATIC,
-                                                methodInsn.owner, Type.getType(methodInsn.desc));
-                if (de != null) {
+                final PrimitiveElementSpecification primitiveMethod =
+                        new PrimitiveElementSpecification(methodInsn.name, methodInsn.getOpcode() == Opcodes.INVOKESTATIC,
+                                                          methodInsn.owner, Type.getType(methodInsn.desc));
 
-                    final Type pReturn = de.getPrimitiveSpec().getPrimitiveType().getReturnType();
-                    final Type dReturn = de.getDifferentiatedType().getReturnType();
+                if (isDifferentiatedMethod(primitiveMethod)) {
+
+                    final Type pReturn = primitiveMethod.getPrimitiveType().getReturnType();
+                    final Type dReturn = transformType(pReturn);
                     if (!pReturn.equals(dReturn)) {
                         // the invocation produces a value that is changed
                         // the produced value is on the top of the instruction successors frame
@@ -562,17 +553,6 @@ public class MethodDifferentiator {
                         }
                     }
 
-                    final Type[] pArgs = de.getPrimitiveSpec().getPrimitiveType().getArgumentTypes();
-                    final Type[] dArgs = de.getDifferentiatedType().getArgumentTypes();
-                    final Frame<TrackingValue> frame = frames.get(methodInsn);
-                    for (int i = 0; i < pArgs.length; ++i) {
-                        if (!pArgs[i].equals(dArgs[i])){
-                            // the invocation consumes a value that is changed
-                            // the consumed value is on the instruction own frame
-                            final TrackingValue stackElement = frame.getStack(frame.getStackSize() - (pArgs.length - i));
-                            changedValues.add(stackElement);
-                        }
-                    }
                 }
             }
         }
@@ -593,12 +573,12 @@ public class MethodDifferentiator {
             final AbstractInsnNode insn = iterator.next();
             if (insn.getType() == AbstractInsnNode.FIELD_INSN) {
                 final FieldInsnNode fieldInsn = (FieldInsnNode) insn;
-                final DifferentiatedElementSpecification de =
-                        getDifferentiatedField(fieldInsn.name,
-                                               fieldInsn.getOpcode() == Opcodes.GETSTATIC ||
-                                               fieldInsn.getOpcode() == Opcodes.PUTSTATIC,
-                                               fieldInsn.owner, Type.getType(fieldInsn.desc));
-                if (de != null) {
+                final PrimitiveElementSpecification primitiveField =
+                        new PrimitiveElementSpecification(fieldInsn.name,
+                                                          fieldInsn.getOpcode() == Opcodes.GETSTATIC ||
+                                                          fieldInsn.getOpcode() == Opcodes.PUTSTATIC,
+                                                          fieldInsn.owner, Type.getType(fieldInsn.desc));
+                if (isDifferentiatedField(primitiveField)) {
                     if (fieldInsn.getOpcode() == Opcodes.GETFIELD || fieldInsn.getOpcode() == Opcodes.GETSTATIC) {
                         // this is a get instruction, it produces a value that is changed
                         // the produced value is on the top of the instruction successors frame
@@ -671,8 +651,7 @@ public class MethodDifferentiator {
                 for (int i = 0; i < produced.getStackSize(); ++i) {
                     final TrackingValue value = produced.getStack(i);
                     if (((i >= beforeStackSize) || (value != before.getStack(i))) &&
-                        value.getType().equals(Type.DOUBLE_TYPE) &&
-                        !converted.contains(value)) {
+                        isTransformableType(value.getType()) && !converted.contains(value)) {
                         values.add(value);
                     }
                 }
@@ -828,7 +807,7 @@ public class MethodDifferentiator {
     public InsnList preserveReferenceDerivativeStructure(final DifferentiatedElementSpecification differentiatedMethod,
                                                          final boolean isStatic, final int dsIndex) {
 
-        final Type transformedType = convertDoubleOrDoubleArray(Type.DOUBLE_TYPE);
+        final Type transformedType = transformType(Type.DOUBLE_TYPE);
         final Type[] parameterTypes = differentiatedMethod.getDifferentiatedType().getArgumentTypes();
         int var = isStatic ? 0 : 1;
         for (int i = 0; i < parameterTypes.length; ++i) {

Modified: commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/GetTransformer.java
URL: http://svn.apache.org/viewvc/commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/GetTransformer.java?rev=1408027&r1=1408026&r2=1408027&view=diff
==============================================================================
--- commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/GetTransformer.java (original)
+++ commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/GetTransformer.java Sun Nov 11 15:12:35 2012
@@ -19,8 +19,8 @@ package org.apache.commons.nabla.forward
 import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
 import org.apache.commons.nabla.DifferentiationException;
 import org.apache.commons.nabla.NablaMessages;
-import org.apache.commons.nabla.forward.DifferentiatedElementSpecification;
 import org.apache.commons.nabla.forward.NablaDifferentiated;
+import org.apache.commons.nabla.forward.PrimitiveElementSpecification;
 import org.apache.commons.nabla.forward.analysis.InstructionsTransformer;
 import org.apache.commons.nabla.forward.analysis.MethodDifferentiator;
 import org.objectweb.asm.Opcodes;
@@ -31,6 +31,7 @@ import org.objectweb.asm.tree.InsnList;
 import org.objectweb.asm.tree.LdcInsnNode;
 import org.objectweb.asm.tree.MethodInsnNode;
 import org.objectweb.asm.tree.TypeInsnNode;
+import org.objectweb.asm.tree.VarInsnNode;
 
 /** Differentiation transformer for GETFIELD/GETSTATIC instructions.
  * <p>Each GETFIELD/GETSTATIC instruction is replaced by an instruction
@@ -52,13 +53,12 @@ public class GetTransformer implements I
         throws DifferentiationException {
 
         final FieldInsnNode fieldInsn = (FieldInsnNode) insn;
-        final DifferentiatedElementSpecification de =
-                methodDifferentiator.getDifferentiatedField(fieldInsn.name,
-                                                            fieldInsn.getOpcode() == Opcodes.GETSTATIC,
-                                                            fieldInsn.owner, Type.getType(fieldInsn.desc));
-        if (de != null) {
+        final PrimitiveElementSpecification primitiveField =
+                new PrimitiveElementSpecification(fieldInsn.name, fieldInsn.getOpcode() == Opcodes.GETSTATIC,
+                                                  fieldInsn.owner, Type.getType(fieldInsn.desc));
+        if (methodDifferentiator.isDifferentiatedField(primitiveField)) {
             // the field is differentiated
-            return getReplacementTransformedField(fieldInsn, methodDifferentiator, de);
+            return getReplacementTransformedField(primitiveField, methodDifferentiator, dsIndex);
         } else {
             // the field is not differentiated, it still lies in the primitive class
             return getReplacementPrimitiveField(fieldInsn, methodDifferentiator);
@@ -69,22 +69,34 @@ public class GetTransformer implements I
      * <p>
      * Transformed fields are kept within the transformed class.
      * </p>
-     * @param fieldInsn original instruction
+     * @param primitiveField specification for the primitive field
      * @param methodDifferentiator method differentiator driving this transformer
      * @param dsIndex index of a reference {@link DerivativeStructure derivative structure} variable
      * @return replacement instructions
      * @exception DifferentiationException if the method differentiator cannot provide
      * a temporary variable
      */
-    private InsnList getReplacementTransformedField(final FieldInsnNode fieldInsn,
+    private InsnList getReplacementTransformedField(final PrimitiveElementSpecification primitiveField,
                                                     final MethodDifferentiator methodDifferentiator,
-                                                    final DifferentiatedElementSpecification de)
+                                                    final int dsIndex)
         throws DifferentiationException {
 
         final InsnList list = new InsnList();
-        list.add(new FieldInsnNode(fieldInsn.getOpcode(),
-                                   methodDifferentiator.getDifferentiatedInternalName(fieldInsn.owner),
-                                   fieldInsn.name, de.getDifferentiatedType().getDescriptor()));
+        list.add(new VarInsnNode(Opcodes.ALOAD, dsIndex));
+        list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+                                    Type.getInternalName(DerivativeStructure.class),
+                                    "getFreeParameters",
+                                    Type.getMethodDescriptor(Type.INT_TYPE)));
+        list.add(new VarInsnNode(Opcodes.ALOAD, dsIndex));
+        list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+                                    Type.getInternalName(DerivativeStructure.class),
+                                    "getOrder",
+                                    Type.getMethodDescriptor(Type.INT_TYPE)));
+        list.add(new MethodInsnNode(primitiveField.isStatic() ? Opcodes.INVOKESTATIC : Opcodes.INVOKESPECIAL,
+                                    methodDifferentiator.getDifferentiatedInternalName(primitiveField.getPrimitiveClass()),
+                                    methodDifferentiator.getGetterName(primitiveField.getName()),
+                                    Type.getMethodDescriptor(methodDifferentiator.transformType(primitiveField.getPrimitiveType()),
+                                                             Type.INT_TYPE, Type.INT_TYPE)));
         return list;
 
     }

Modified: commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/InvokeNonMathTransformer.java
URL: http://svn.apache.org/viewvc/commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/InvokeNonMathTransformer.java?rev=1408027&r1=1408026&r2=1408027&view=diff
==============================================================================
--- commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/InvokeNonMathTransformer.java (original)
+++ commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/InvokeNonMathTransformer.java Sun Nov 11 15:12:35 2012
@@ -17,6 +17,8 @@
 package org.apache.commons.nabla.forward.instructions;
 
 import org.apache.commons.nabla.DifferentiationException;
+import org.apache.commons.nabla.forward.DifferentiatedElementSpecification;
+import org.apache.commons.nabla.forward.PrimitiveElementSpecification;
 import org.apache.commons.nabla.forward.analysis.InstructionsTransformer;
 import org.apache.commons.nabla.forward.analysis.MethodDifferentiator;
 import org.objectweb.asm.Opcodes;
@@ -40,7 +42,7 @@ public class InvokeNonMathTransformer im
         final MethodInsnNode methodInsn = (MethodInsnNode) insn;
 
         // build transformed method signature based on stack elements
-        final Type transformedType     = methodDifferentiator.convertDoubleOrDoubleArray(Type.DOUBLE_TYPE);
+        final Type transformedType     = methodDifferentiator.transformType(Type.DOUBLE_TYPE);
         final Type primitiveMethodType = Type.getMethodType(methodInsn.desc);
         final Type[] argumentTypes     = new Type[primitiveMethodType.getArgumentTypes().length];
         for (int i = 0; i < argumentTypes.length; ++i) {
@@ -49,13 +51,17 @@ public class InvokeNonMathTransformer im
                                transformedType : methodDifferentiator.stackElementType(insn, index);
         }
         final Type returnType =
-                methodDifferentiator.convertDoubleOrDoubleArray(primitiveMethodType.getReturnType());
+                methodDifferentiator.transformType(primitiveMethodType.getReturnType());
         final Type differentiatedMethodType = Type.getMethodType(returnType, argumentTypes);
 
         // request the global differentiator to differentiate the invoked method
-        methodDifferentiator.requestMethodDifferentiation(methodInsn.name,
-                                                          methodInsn.getOpcode() == Opcodes.INVOKESTATIC,
-                                                          methodInsn.owner, primitiveMethodType, differentiatedMethodType);
+        final PrimitiveElementSpecification primitive =
+                new PrimitiveElementSpecification(methodInsn.name,
+                                                  methodInsn.getOpcode() == Opcodes.INVOKESTATIC,
+                                                  methodInsn.owner, primitiveMethodType);
+        final DifferentiatedElementSpecification differentiated =
+                new DifferentiatedElementSpecification(primitive, differentiatedMethodType);
+        methodDifferentiator.requestMethodDifferentiation(differentiated);
 
         // create the transformed instruction
         final InsnList list = new InsnList();

Modified: commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/PutTransformer.java
URL: http://svn.apache.org/viewvc/commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/PutTransformer.java?rev=1408027&r1=1408026&r2=1408027&view=diff
==============================================================================
--- commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/PutTransformer.java (original)
+++ commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/PutTransformer.java Sun Nov 11 15:12:35 2012
@@ -16,10 +16,11 @@
  */
 package org.apache.commons.nabla.forward.instructions;
 
-import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
 import org.apache.commons.nabla.DifferentiationException;
 import org.apache.commons.nabla.NablaMessages;
+import org.apache.commons.nabla.forward.DifferentiatedElementSpecification;
 import org.apache.commons.nabla.forward.NablaDifferentiated;
+import org.apache.commons.nabla.forward.PrimitiveElementSpecification;
 import org.apache.commons.nabla.forward.analysis.InstructionsTransformer;
 import org.apache.commons.nabla.forward.analysis.MethodDifferentiator;
 import org.objectweb.asm.Opcodes;
@@ -58,45 +59,50 @@ public class PutTransformer implements I
                                    final MethodDifferentiator methodDifferentiator,
                                    final int dsIndex)
         throws DifferentiationException {
+
+        final FieldInsnNode fieldInsn = (FieldInsnNode) insn;
+        final boolean isStatic = fieldInsn.getOpcode() == Opcodes.PUTSTATIC;
+        final PrimitiveElementSpecification primitiveField =
+                new PrimitiveElementSpecification(fieldInsn.name, isStatic,
+                                                  fieldInsn.owner, Type.getType(fieldInsn.desc));
         if (methodDifferentiator.stackElementIsConverted(insn, 0)) {
-            return getReplacementTransformedField((FieldInsnNode) insn, methodDifferentiator, dsIndex);
+            // we need to add a new field in the transformed class
+            final Type differentiatedFieldType =
+                    methodDifferentiator.transformType(Type.getType(fieldInsn.desc));
+            final DifferentiatedElementSpecification differentiatedField =
+                    new DifferentiatedElementSpecification(primitiveField, differentiatedFieldType);
+            methodDifferentiator.requestFieldDifferentiation(differentiatedField);
+        }
+
+        if (methodDifferentiator.isDifferentiatedField(primitiveField)) {
+            return getReplacementTransformedField(primitiveField, methodDifferentiator);
         } else {
-            return getReplacementPrimitiveField((FieldInsnNode) insn, methodDifferentiator);
+            return getReplacementPrimitiveField(fieldInsn, methodDifferentiator);
         }
+
     }
 
     /** Get the replacement instructions when the field type is transformed.
      * <p>
      * Transformed fields are kept within the transformed class.
      * </p>
-     * @param insn original instruction
+     * @param primitiveField specification for the primitive field
      * @param methodDifferentiator method differentiator driving this transformer
-     * @param dsIndex index of a reference {@link DerivativeStructure derivative structure} variable
+     * @param insn original instruction
      * @return replacement instructions
      * @exception DifferentiationException if the method differentiator cannot provide
      * a temporary variable
      */
-    private InsnList getReplacementTransformedField(final FieldInsnNode insn,
-                                                    final MethodDifferentiator methodDifferentiator,
-                                                    final int dsIndex)
+    private InsnList getReplacementTransformedField(final PrimitiveElementSpecification primitiveField,
+                                                    final MethodDifferentiator methodDifferentiator)
         throws DifferentiationException {
 
-        final Type primitiveFieldType = Type.getType(insn.desc);
-        if (!methodDifferentiator.isDoubleOrDoubleArray(primitiveFieldType)) {
-            // TODO handle double array types
-            throw new RuntimeException("PUTFIELD/PUTSTATIC not handled yet for non-double fields");            
-        }
-        final Type differentiatedFieldType = methodDifferentiator.convertDoubleOrDoubleArray(primitiveFieldType);
-
-        // we need to add a new field in the transformed class
-        final boolean isStatic = insn.getOpcode() == Opcodes.PUTSTATIC;
-        methodDifferentiator.requestFieldDifferentiation(insn.name, isStatic, insn.owner,
-                                                         primitiveFieldType, differentiatedFieldType);
-
         final InsnList list = new InsnList();
-        list.add(new FieldInsnNode(insn.getOpcode(),
-                                   methodDifferentiator.getDifferentiatedInternalName(insn.owner),
-                                   insn.name, differentiatedFieldType.getDescriptor()));
+        list.add(new MethodInsnNode(primitiveField.isStatic() ? Opcodes.INVOKESTATIC : Opcodes.INVOKESPECIAL,
+                                    methodDifferentiator.getDifferentiatedInternalName(primitiveField.getPrimitiveClass()),
+                                    methodDifferentiator.getSetterName(primitiveField.getName()),
+                                    Type.getMethodDescriptor(Type.VOID_TYPE,
+                                                             methodDifferentiator.transformType(primitiveField.getPrimitiveType()))));
         return list;
 
     }

Modified: commons/sandbox/nabla/trunk/src/test/java/org/apache/commons/nabla/forward/ForwardModeDifferentiatorTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/nabla/trunk/src/test/java/org/apache/commons/nabla/forward/ForwardModeDifferentiatorTest.java?rev=1408027&r1=1408026&r2=1408027&view=diff
==============================================================================
--- commons/sandbox/nabla/trunk/src/test/java/org/apache/commons/nabla/forward/ForwardModeDifferentiatorTest.java (original)
+++ commons/sandbox/nabla/trunk/src/test/java/org/apache/commons/nabla/forward/ForwardModeDifferentiatorTest.java Sun Nov 11 15:12:35 2012
@@ -16,6 +16,8 @@
  */
 package org.apache.commons.nabla.forward;
 
+import java.lang.reflect.Method;
+
 import org.apache.commons.math3.analysis.UnivariateFunction;
 import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
 import org.apache.commons.math3.analysis.differentiation.UnivariateDifferentiableFunction;
@@ -151,7 +153,7 @@ public class ForwardModeDifferentiatorTe
 
     @Test
     public void testDifferentiateWRTDifferentArguments() {
-        checkReference(new ReferenceFunction() {
+        UnivariateDifferentiableFunction udf = checkReference(new ReferenceFunction() {
             private double f(double a, double b) {
                 return a / b;
             }
@@ -164,6 +166,14 @@ public class ForwardModeDifferentiatorTe
             public double firstDerivative(double t) { return 0.5 - 1.0 / (t * t); }
         }, -5.25, 5, 20, 8.0e-15);
 
+        int countF = 0;
+        for (final Method method : udf.getClass().getDeclaredMethods()) {
+            if (method.getName().equals("f")) {
+                ++countF;
+            }
+        }
+        Assert.assertEquals(2, countF);
+
     }
 
     @Test
@@ -255,25 +265,49 @@ public class ForwardModeDifferentiatorTe
 
     @Test
     public void testFieldAsIntermediateData() {
-        checkReference(new ReferenceFunction() {
 
-            // this field is used to store data transfered from value to f
-            private double intermediateData;
+        IntermediateDataFunction function = new IntermediateDataFunction();
+        UnivariateDifferentiableFunction udf = checkReference(function, -5.25, 5, 20, 8.0e-15);
 
-            private double f() {
-                return 2 * intermediateData;
-            }
+        // calls to the differentiated function must change the original
+        // intermediate data fields in the primitive function as they are linked together
+        Assert.assertEquals(6.5, udf.value(new DerivativeStructure(1, 1, 0, 1.0)).getValue(), 1.0e-15);
+        Assert.assertEquals(3.5, function.getInstanceData(), 1.0e-15);
+        Assert.assertEquals(0.5, IntermediateDataFunction.getStaticData(), 1.0e-15);
+        Assert.assertEquals(7.5, udf.value(new DerivativeStructure(1, 1, 0, 3.0)).getValue(), 1.0e-15);
+        Assert.assertEquals(4.5, function.getInstanceData(), 1.0e-15);
+        Assert.assertEquals(1.5, IntermediateDataFunction.getStaticData(), 1.0e-15);
 
-            public double value(double t) {
-                intermediateData = t + 3.0;
-                return f();
-            }
+    }
 
-            public double firstDerivative(double t) {
-                return 2.0;
-            }
+    public static class IntermediateDataFunction implements ReferenceFunction {
 
-        }, -5.25, 5, 20, 8.0e-15);
+        // these fields are changed as side effects of each call to the value method
+        // as they are used to transfer data to the f method
+        private static double staticData;
+        private double instanceData;
+
+        private double f() {
+            return 2 * instanceData - staticData;
+        }
+
+        public double value(double t) {
+            staticData   = 0.5 * t;
+            instanceData = staticData + 3.0;
+            return f();
+        }
+
+        public static double getStaticData() {
+            return staticData;
+        }
+
+        public double getInstanceData() {
+            return instanceData;
+        }
+
+        public double firstDerivative(double t) {
+            return 0.5;
+        }
     }
 
     @Test



Mime
View raw message