def test_null_ops(self): for script in [ [types.Five(), types.Zero(), types.Add()], [types.Zero(), types.Five(), types.Add()], [types.Five(), types.Zero(), types.Sub()], ]: self._do_test('OP_5', script)
def replace_shortcut_ops(instructions): """Replace opcodes with a corresponding shortcut form.""" optimizations = [] # Replace division by 2. # OP_2 OP_DIV -> OP_2DIV optimizations.append(([types.Two(), types.Div()], lambda values: [types.Div2()])) # Replace subtraction by 1. # OP_1 OP_SUB -> OP_1SUB optimizations.append(([types.One(), types.Sub()], lambda values: [types.Sub1()])) # Replace 1 * -1 with -1. # OP_1 OP_NEGATE -> OP_1NEGATE optimizations.append(([types.One(), types.Negate()], lambda values: [types.NegativeOne()])) # Replace addition by 1. # OP_1 OP_ADD -> OP_1ADD for permutation in permutations([types.Push(), types.One()]) + permutations([types.SmallIntOpCode(), types.One()]): idx = 0 if not isinstance(permutation[0], types.One) else 1 optimizations.append((permutation + [types.Add()], lambda values, idx=idx: [values[idx], types.Add1()])) optimizations.append(([types.Assumption(), types.One(), types.Add()], lambda values: [values[0], types.Add1()])) # Replace multiplication by 2. # OP_2 OP_MUL -> OP_2MUL for permutation in permutations([types.Push(), types.Two()]) + permutations([types.SmallIntOpCode(), types.Two()]): idx = 0 if not isinstance(permutation[0], types.Two) else 1 optimizations.append((permutation + [types.Mul()], lambda values, idx=idx: [values[idx], types.Mul2()])) optimizations.append(([types.Assumption(), types.Two(), types.Mul()], lambda values: [values[0], types.Mul2()])) for template, callback in optimizations: instructions.replace_template(template, callback, strict=False)
def test_shortcut_ops(self): for script in [ [types.Five(), types.One(), types.Add()], [types.One(), types.Five(), types.Add()], ]: self._do_test('OP_5 OP_1ADD', script) self._do_test('OP_1ADD', [types.Assumption('testItem'), types.One(), types.Add()]) script = [types.Five(), types.One(), types.Sub()] self._do_test('OP_5 OP_1SUB', script) for script in [ [types.Five(), types.Two(), types.Mul()], [types.Two(), types.Five(), types.Mul()], ]: self._do_test('OP_5 OP_2MUL', script) self._do_test('OP_2MUL', [types.Assumption('testItem'), types.Two(), types.Mul()]) script = [types.Five(), types.Two(), types.Div()] self._do_test('OP_5 OP_2DIV', script) script = [types.Five(), types.One(), types.Negate()] self._do_test('OP_5 OP_1NEGATE', script)
def test_assume_to_pick_or_roll(self): script = [types.Five(), types.Assumption('testItem'), types.Add()] self._do_test('OP_5 OP_ADD', script) self._reset_table(['testItem']) script = [types.Five(), types.Five(), types.Assumption('testItem'), types.Add()] self._do_test('OP_5 OP_5 OP_2 OP_ROLL OP_ADD', script) self._reset_table(['testItem']) script = [types.Five(), types.Five(), types.Assumption('testItem'), types.Add(), types.Assumption('testItem')] self._do_test('OP_5 OP_5 OP_2 OP_PICK OP_ADD OP_2 OP_ROLL', script)
def shorten_commutative_operations(instructions): """Remove ops that change the order of commutative operations.""" optimizations = [] for op in [types.Add(), types.Mul(), types.BoolAnd(), types.BoolOr(), types.NumEqual(), types.NumEqualVerify(), types.NumNotEqual(), types.Min(), types.Max(), types.And(), types.Or(), types.Xor(), types.Equal(), types.EqualVerify(), ]: template = [types.Swap(), op] optimizations.append((template, lambda values: values[1:])) for template, callback in optimizations: instructions.replace_template(template, callback)
def replace_null_ops(instructions): """Replace operations that do nothing.""" # Remove subtraction by 0. # OP_0 OP_SUB -> _ optimizations = [([types.Zero(), types.Sub()], lambda values: [])] # Remove addition by 0. # OP_0 OP_ADD -> _ for permutation in permutations([None, types.Zero()]): idx = 0 if permutation[0] is None else 1 optimizations.append((permutation + [types.Add()], lambda values, idx=idx: [values[idx]])) for template, callback in optimizations: instructions.replace_template(template, callback)
def test_implicit_assume(self): script = [types.Assumption('testItem'), types.Five(), types.Add()] self._do_test('OP_5 OP_ADD', script)