def pohlighellman(a, b, count, simpleDlog=autoshanks): """ Performs Pohlig-Hellman algorithm to solve the discrete logarithm. Requires the factorization of count to be computed, and relies on ent.factor(...) to achieve that. The routine uses another algorithm to solve simpler DLOG problems, shanks as default. Input: a 'Base' of the discrete logarithm b 'Argument' of the discrete logarithm count Number of elements in the group (of a and b) simpleDlog A callable that computes DLOG in a smaller group. The signature and return value must be the same as autoshanks; actually this argument defaults to autoshanks(...). Output: An integer l such that a*l=b (the smallest in the range 0...count-1). Remarks: Uses chineseremainder(...) to combine the partial results. """ # first of all let's factor count factorization=ent.factor(count) l=range(0,len(factorization)) li=0 for (p, e) in factorization: g=(count//p)*a if g.isIdentity(): # it may happen that g=O! # ..still to check, but a couple of tests showed that # this works. l[li]=((p**e)-1, p**e) li+=1 continue A=0*a # 0 in the G group bs=range(0, e) for i in bigrange(0, e): if i>0: A=A+bs[i-1]*(p**(i-1))*a B=(b-A)*(count//(p**(i+1))) bs[i]=simpleDlog(g, B, p) # compute l_k l[li]=0 for i in bigrange(e, 0, -1): l[li]*=p l[li]+=bs[i-1] # prepare l to be input for chineseremainder l[li]=(l[li], p**e) li+=1 return chineseremainder(l)
def orderInFactorGroup(P, lp, Q, lq): """ This routine computes the order of Q's equivalence class in the quotient group C_K/<P>. Input: P A rational point lp The order of P Q Another rational point lq The order of Q Output: Integer m such that m*[Q]=[O] in C_K/<P>. Remarks: The routine doesn't check if P and Q are either the identity, or if they belong to the same group (although the algorithm should fail in that case, because addition and equality are not defined). This can be a quite expensive routine, and makes use of the factorization of lq (achieved through ent.factor(...)). It is essentially intended to be called from inside EC.cardinality(). """ h=int(math.ceil(math.sqrt(lp))) # precompute baby steps step=ECPt.identity() babysteps=[step] for i in bigrange(1, h): step=step+P babysteps.insert(dlog.find_insertion_index(step, babysteps), step) # precompute giant steps hP=h*P step=ECPt.identity() giantsteps=[step] for i in bigrange(1, h): step=step+hP giantsteps.insert(dlog.find_insertion_index(step, giantsteps), step) # let's factor l_Q factorization=ent.factor(lq) d=lq # for each prime factor in the factorization for (p,e) in factorization: QQ=Q*(d//p) nextFactor=False while not nextFactor: # look for each QQ-R in babysteps. # if found, update d and try again with # the same factor. Otherwise, next prime found=False for (R, i) in giantsteps: lookfor=QQ-R if dlog.find_item(lookfor, babysteps)!=None: d=d//p found=True break if not found: nextFactor=True return d # the needed integer
def cardinality(self): """ This routine computes the exact cardinality of the group of rational points over the elliptic curve. The result is cached, the computation is done only once. Output: The cardinality. Remarks: The routine uses ECPt.minOrderWithConstraints(...), ECPt.orderInFactorGroup and ent.factor, therefore might be really expensive in terms of efficiency. """ if self._cardinality>=0: return self._cardinality P=self.pickPoint() # try to get order b=self._p+1-int(math.floor(2*math.sqrt(self._p))) c=self._p+1+int(math.ceil(2*math.sqrt(self._p))) result=P.minOrderWithConstraints(b, c, 0, 1) if not isinstance(result, tuple): # we've finished! self._cardinality=result return result # we have the order of P lp=result[1] while True: # let's pick another point Q=self.pickPoint() while Q==P: Q=self.pickPoint() # different, please # another run of minOrder... result=Q.minOrderWithConstraints(b, c, 0, lp) if not isinstance(result, tuple): # we've finished self._cardinality=result return result lqp=result[1] # we need l_Q lq=lqp*lp factorization=ent.factor(lq) for (p, e) in factorization: while ((lq//p)*Q).isIdentity(): lq=lq//p # we have P, l_P, Q, l_Q, we can run another algorithm t=ECPt.orderInFactorGroup(P, lp, Q, lq) # let's check if it's ok if lp*t>2*int(math.floor(2*math.sqrt(p))): # #C_K is the only number in [b,c] divisible by lpt temp=math.ceil(b/float(lp*t)) self._cardinality=int(temp)*lp*t return self._cardinality
from pyx import canvas, document, path from ent import factor from math import sin, cos, sqrt, pi n = 100_000 ca = canvas.canvas() phi = (1 + sqrt(5)) / 2.0 for j in range(n): i = j + 1 r = sqrt(i) theta = i * 2 * pi / (phi * phi) x = cos(theta) * r y = -sin(theta) * r factors = factor(i) if (len(factors) > 1): radius = 0.05 * pow(2, len(factors) - 1) ca.fill(path.circle(x, y, radius)) d = document.document(pages=[ document.page(ca, paperformat=document.paperformat.A4, fittosize=1) ]) d.writePDFfile('spiral_vogel_1e5.pdf')
# set up the tool import utg utg.capture_mode() # instrumentalize the target module import ent utg.capture_module_functions(ent) # run example cases ent.factor(2313) ent.primitive_root(2311) # instrumentalize one function here from utg import capture @capture def raising_func(): raise Exception("This should be raised") # run the example try: raising_func() except: pass # setup captures import ent_class E = ent_class.Ent() utg.capture_object_methods(E) utg.capture_object_properties(E) E.the_answer = 42 utg.capture_class(ent_class.InsideEnt)