templates.fixed_precision
1# Fixed precision computations - Example for illustrative purposes only. 2 3import smartpy as sp 4 5 6""" 7This has been inspired by 8 9https://github.com/Sophia-Gold/michelson/blob/master/log2fix.tz 10 11http://www.claysturner.com/dsp/BinaryLogarithm.pdf 12 131) Initialize result to 0: y = 0. 142)Initialize mantissa-bit decimal value to 0.5: b = 1/2. 15 163) While x < 1, x = 2x, y = y - 1. 174) While x >= 2, x = x/2, y = y + 1. 18 196)Square: x = x * x. 207) If x > 2, x = x/2, y = y + b. 218) Scale for next bit: b = b/2. 229)Go to Step 6 and repeat until desired number of mantissa bits are found. 23 2410) Final log(x) value: y. 25""" 26 27 28@sp.module 29def main(): 30 class MyContract(sp.Contract): 31 def __init__(self, precision): 32 self.private.precision = sp.cast(precision, sp.nat) 33 self.data.value = 0 34 35 @sp.entrypoint 36 def log(self, params): 37 assert params != 0 38 y = 0 39 x = params 40 while x < 1 << self.private.precision: 41 x <<= 1 42 y -= sp.to_int(1 << self.private.precision) 43 while x >= 2 << self.private.precision: 44 x >>= 1 45 y += sp.to_int(1 << self.private.precision) 46 b = 1 << sp.as_nat(self.private.precision - 1) 47 while 0 < b: 48 x = (x * x) >> self.private.precision 49 if x > 2 << self.private.precision: 50 x >>= 1 51 y += sp.to_int(b) 52 b >>= 1 53 self.data.value = y 54 55 56def direct(x, precision): 57 import math 58 59 return int((math.log(x / (1 << precision)) / math.log(2)) * (1 << precision)) 60 61 62@sp.add_test() 63def test(): 64 scenario = sp.test_scenario("FixedPrecision", main) 65 scenario.h1("Fixed Precision Computations") 66 c1 = main.MyContract(precision=16) 67 scenario += c1 68 69 def check_ok(scenario, n): 70 d = direct(n, 16) 71 scenario.h3("Computing log(%i / 65536)" % n) 72 scenario.p("Direct computation %i" % direct(n, 16)) 73 c1.log(n) 74 scenario.verify(abs(c1.data.value - d) < 2) 75 76 check_ok(scenario, 1000000) 77 check_ok(scenario, 65535) 78 check_ok(scenario, 65536) 79 check_ok(scenario, 65537) 80 check_ok(scenario, 131071) 81 check_ok(scenario, 131072) 82 check_ok(scenario, 131073) 83 check_ok(scenario, 1)
def
direct(x, precision):