[2/2]
class ListGroup (Group):
@ classmethod
def kind (cls):
return "list"
def __init__ (self, groups):
self.groups = groups
def eval (self, ctx, stackpos):
MC = ctx ["matrixclass"]
stack = ctx ["stack" ]
gs = self.groups
count = len (gs)
if count < 1:
MC.copyinto (MC.I, stack [stackpos])
return
if count == 1:
gs [0].eval (ctx, stackpos)
return
div, mod = divmod (count - 1, 2)
if mod:
now = stackpos + 1
other = stackpos
else:
now = stackpos
other = stackpos + 1
Stack.ensure (stack, stackpos + 3, MC)
factor = stackpos + 2
mfactor = stack [factor]
mnow = stack [now ]
mother = stack [other ]
gs [0].eval (ctx, now)
mul = MC.mul
gspos = 1
for k in range (div):
gs [gspos ].eval (ctx, factor)
mul (mnow, mfactor, mother)
gs [gspos + 1].eval (ctx, factor)
mul (mother, mfactor, mnow)
gspos += 2
if mod:
gs [gspos].eval (ctx, factor)
mul (mnow, mfactor, mother)
class ExpoGroup (Group):
@ classmethod
def kind (cls):
return "expo"
def __init__ (self, base, expo, *, alwaysevalbase = False):
self.base = base
self.expo = expo
self.alwaysevalbase = alwaysevalbase
def eval (self, ctx, stackpos):
MC = ctx ["matrixclass"]
stack = ctx ["stack" ]
base = self.base
expo = self.expo
always = self.alwaysevalbase
if (expo < 1) and not always:
MC.copyinto (MC.I, stack [stackpos])
return
Stack.ensure (stack, stackpos + 2, MC)
base.eval (ctx, stackpos)
Expo.bits (stack [stackpos], expo, stack, stackpos + 1, MC)
MC.copyinto (stack [stackpos + 1], stack [stackpos])
class Spec:
@ classmethod
def kind (cls):
pass
@ classmethod
def targetfloat (cls):
pass
class StarSpec (Spec):
@ classmethod
def kind (cls):
return "star"
def __init__ (self, group):
self.group = group
class Compiler:
@ staticmethod
def fixedlimit (spec, limit):
what = spec.kind ()
ret = getattr (Compiler, "fixedlimit_" + what) (spec, limit)
return ret
@ staticmethod
def fixedlimit_star (spec, limit):
if limit < 1:
return {
"group": EmptyGroup (),
"count": 0,
}
g = spec.group
what = g.kind ()
if what != "fixed":
raise ValueError (what)
fs = g.fixedstr
fslen = len (fs)
if fslen < 1:
raise ValueError (fslen)
div, mod = divmod (limit, fslen)
if mod:
h = ListGroup ([
ExpoGroup (g, div),
FixedGroup (fs [:mod])])
else:
h = ExpoGroup (g, div)
return {
"group": h,
"count": limit,
}
class Specs:
class Phi (StarSpec):
@ classmethod
def targetfloat (cls):
return (1 + math.sqrt (5)) / 2
def __init__ (self):
StarSpec.__init__ (self, FixedGroup ("RL"))
class Sqrt2 (StarSpec):
@ classmethod
def targetfloat (cls):
return math.sqrt (2)
def __init__ (self):
StarSpec.__init__ (self, FixedGroup ("RLLR"))
class Sqrt3 (StarSpec):
@ classmethod
def targetfloat (cls):
return math.sqrt (3)
def __init__ (self):
StarSpec.__init__ (self, FixedGroup ("RLR"))
class Sqrt5 (StarSpec):
@ classmethod
def targetfloat (cls):
return math.sqrt (5)
def __init__ (self):
StarSpec.__init__ (self, FixedGroup ("RRLLLLRR"))
class Sqrt7 (StarSpec):
@ classmethod
def targetfloat (cls):
return math.sqrt (7)
def __init__ (self):
StarSpec.__init__ (self, FixedGroup ("RRLRLRR"))
def work_speclimit (spec, limit):
log = print
M = Matrix
C = Compiler
slots = 2
mstack = Stack.alloc (slots, M)
target = spec.targetfloat ()
ctx = {
"matrixclass": M,
"stack": mstack,
}
log ("target {:.15f}".format (target))
ret = C.fixedlimit (spec, limit)
group = ret ["group"]
group.eval (ctx, 1)
M.mul (M.S, mstack [1], mstack [0])
a, b = M.pair (mstack [0])
log ("result {:.15f}".format (a / b))
log ("{:d}".format (a))
log ("{:d}".format (b))
log ("stack {:d}".format (len (mstack)))