1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.nabla.forward.arithmetic;
18
19 import org.apache.commons.nabla.DifferentiationException;
20 import org.apache.commons.nabla.forward.analysis.InstructionsTransformer;
21 import org.apache.commons.nabla.forward.analysis.MethodDifferentiator;
22 import org.objectweb.asm.Opcodes;
23 import org.objectweb.asm.Type;
24 import org.objectweb.asm.tree.AbstractInsnNode;
25 import org.objectweb.asm.tree.InsnList;
26 import org.objectweb.asm.tree.InsnNode;
27 import org.objectweb.asm.tree.MethodInsnNode;
28 import org.objectweb.asm.tree.VarInsnNode;
29
30
31
32
33 public class DRemTransformer implements InstructionsTransformer {
34
35
36 private static final String REMAINDER_METHOD = "remainder";
37
38
39 private static final String VALUE_GETTER_METHOD = "getValue";
40
41
42 private static final String MULTIPLY_METHOD = "multiply";
43
44
45 private static final String ADD_METHOD = "add";
46
47
48 private final boolean stack0Converted;
49
50
51 private final boolean stack1Converted;
52
53
54
55
56
57 public DRemTransformer(final boolean stack0Converted, final boolean stack1Converted) {
58 this.stack0Converted = stack0Converted;
59 this.stack1Converted = stack1Converted;
60 }
61
62
63 public InsnList getReplacement(final AbstractInsnNode insn,
64 final MethodDifferentiator methodDifferentiator)
65 throws DifferentiationException {
66
67 final InsnList list = new InsnList();
68
69 if (stack1Converted) {
70 if (stack0Converted) {
71 list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, DS_TYPE.getInternalName(),
72 REMAINDER_METHOD,
73 Type.getMethodDescriptor(DS_TYPE, DS_TYPE)));
74 } else {
75 list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, DS_TYPE.getInternalName(),
76 REMAINDER_METHOD,
77 Type.getMethodDescriptor(DS_TYPE, Type.DOUBLE_TYPE)));
78 }
79 } else {
80
81
82 final int tmp1 = methodDifferentiator.getTmp(1);
83
84
85 list.add(new InsnNode(Opcodes.DUP_X2));
86 list.add(new InsnNode(Opcodes.POP));
87 list.add(new VarInsnNode(Opcodes.DSTORE, tmp1));
88 list.add(new InsnNode(Opcodes.DUP));
89 list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, DS_TYPE.getInternalName(),
90 VALUE_GETTER_METHOD,
91 Type.getMethodDescriptor(Type.DOUBLE_TYPE)));
92 list.add(new InsnNode(Opcodes.DUP2));
93 list.add(new VarInsnNode(Opcodes.DLOAD, tmp1));
94 list.add(new InsnNode(Opcodes.DUP2_X2));
95 list.add(new InsnNode(Opcodes.POP2));
96 list.add(new InsnNode(Opcodes.DREM));
97 list.add(new VarInsnNode(Opcodes.DLOAD, tmp1));
98 list.add(new InsnNode(Opcodes.DSUB));
99 list.add(new InsnNode(Opcodes.DUP2_X2));
100 list.add(new InsnNode(Opcodes.POP2));
101 list.add(new InsnNode(Opcodes.DDIV));
102 list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, DS_TYPE.getInternalName(),
103 MULTIPLY_METHOD,
104 Type.getMethodDescriptor(DS_TYPE, Type.DOUBLE_TYPE)));
105 list.add(new VarInsnNode(Opcodes.DLOAD, tmp1));
106 list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, DS_TYPE.getInternalName(),
107 ADD_METHOD,
108 Type.getMethodDescriptor(DS_TYPE, Type.DOUBLE_TYPE)));
109
110 }
111
112 return list;
113
114 }
115
116 }