View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.nabla.forward.instructions;
18  
19  import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
20  import org.apache.commons.nabla.DifferentiationException;
21  import org.apache.commons.nabla.forward.analysis.InstructionsTransformer;
22  import org.apache.commons.nabla.forward.analysis.MethodDifferentiator;
23  import org.objectweb.asm.Opcodes;
24  import org.objectweb.asm.Type;
25  import org.objectweb.asm.tree.AbstractInsnNode;
26  import org.objectweb.asm.tree.InsnList;
27  import org.objectweb.asm.tree.InsnNode;
28  import org.objectweb.asm.tree.LdcInsnNode;
29  import org.objectweb.asm.tree.MethodInsnNode;
30  import org.objectweb.asm.tree.TypeInsnNode;
31  import org.objectweb.asm.tree.VarInsnNode;
32  
33  /** Differentiation transformer for promoting a double on the stack
34   * to a derivative structure.
35   * @version $Id$
36   */
37  public class WideningTransformer implements InstructionsTransformer {
38  
39      /** Simple constructor.
40       */
41      public WideningTransformer() {
42      }
43  
44      /** {@inheritDoc} */
45      public InsnList getReplacement(final AbstractInsnNode insn,
46                                     final MethodDifferentiator methodDifferentiator)
47          throws DifferentiationException {
48  
49          final InsnList list = new InsnList();
50  
51          // copy the instruction creating the double (DCONST_0, DCONST_1, LDC, I2D, L2D or F2D)
52          if (insn.getOpcode() == Opcodes.LDC) {
53              list.add(new LdcInsnNode(((LdcInsnNode) insn).cst));
54          } else {
55              list.add(new InsnNode(insn.getOpcode()));
56          }
57  
58          // operand stack initial state: d
59          list.add(new TypeInsnNode(Opcodes.NEW,
60                                    Type.getInternalName(DerivativeStructure.class)));      // => d y_ds
61          list.add(new InsnNode(Opcodes.DUP_X2));                                           // => y_ds d y_ds
62          list.add(new InsnNode(Opcodes.DUP_X2));                                           // => y_ds y_ds d y_ds
63          list.add(new InsnNode(Opcodes.POP));                                              // => y_ds y_ds d
64          list.add(new VarInsnNode(Opcodes.ALOAD, methodDifferentiator.getInputDSIndex())); // => y_ds y_ds d x_ds
65          list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
66                                      Type.getInternalName(DerivativeStructure.class),
67                                      "getFreeParameters",
68                                      Type.getMethodDescriptor(Type.INT_TYPE)));            // => y_ds y_ds d params
69          list.add(new VarInsnNode(Opcodes.ALOAD, 1));                                      // => y_ds y_ds d params x_ds
70          list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
71                                      Type.getInternalName(DerivativeStructure.class),
72                                      "getOrder",
73                                      Type.getMethodDescriptor(Type.INT_TYPE)));            // => y_ds y_ds d params order
74          list.add(new InsnNode(Opcodes.DUP2_X2));                                          // => y_ds y_ds params order d params order
75          list.add(new InsnNode(Opcodes.POP2));                                             // => y_ds y_ds params order d
76          list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
77                                      Type.getInternalName(DerivativeStructure.class),
78                                      "<init>",
79                                      Type.getMethodDescriptor(Type.VOID_TYPE,
80                                                               Type.INT_TYPE,
81                                                               Type.INT_TYPE,
82                                                               Type.DOUBLE_TYPE)));         // => y_ds
83  
84          return list;
85  
86      }
87  
88  }