Hi, > Could you post some cool impressive benchmarks? :-) > > william
ok :-) Here the result for finding one root in GF(p) where p is 128, 256 and 512 bit prime: Results for 128 bit prime: Original: Time: CPU 0.04 s, Wall: 0.04 s Number of roots found: 1 Tonelli: Time: CPU 0.00 s, Wall: 0.00 s Number of roots found: 1 Results for 256 bit prime: Original: Time: CPU 0.96 s, Wall: 0.96 s Number of roots found: 0 Tonelli: Time: CPU 0.00 s, Wall: 0.00 s Number of roots found: 0 Results for 512 bit prime: Original: Time: CPU 9.94 s, Wall: 10.09 s Number of roots found: 0 Tonelli: Time: CPU 0.00 s, Wall: 0.00 s Number of roots found: 0 This shows only that the old implementation was inefficient for large p. The results for the original implementation for 256 and 512 bit are not contained in the following results, since sqrt(a) returned an error for the 256 bit and 512 bit case. Here are the results for 100 random values for a. Find x: x^2==a mod p Results for 128 bit prime: Original: Time: CPU 5.36 s, Wall: 5.41 s Number of roots found: 47 Tonelli: Time: CPU 0.07 s, Wall: 0.08 s Number of roots found: 47 Results for 256 bit prime: Tonelli: Time: CPU 0.10 s, Wall: 0.10 s Number of roots found: 48 Results for 512 bit prime: Tonelli: Time: CPU 0.30 s, Wall: 0.33 s Number of roots found: 50 Here is the complete code I used: def step3(b,p,r,x): # Step 3: Find exponent if GF(p)(b) == GF(p)(1): return b,r,x,0 m = 0 while GF(p)(b**(2**m)) != 1: m = m + 1 if m == r: return b,r,0,0 return b,r,x,m def s_root(a,p): # Step 0: Determine q: q = 0 e = 0 while q % 2 != 1: e = e+1 q = (p-1) / 2**e # Step 1: Find generator n = ZZ.random_element() while kronecker(n,p) != -1: n = ZZ.random_element() n = GF(p)(n) z = GF(p)(n**q) # Step 2: Initialize y = z r = e a = GF(p)(a) x = GF(p)(a**((q-1)/2)) b = GF(p)(a*(x**2)) x = GF(p)(a*x) # Step 3: b,r,x,m = step3(b,p,r,x) # Step 4: Reduce exponent while ZZ(m) != ZZ(0): t = GF(p)(y**(2**(r-m-1))) y = GF(p)(t**2) r = GF(p)(m) x = GF(p)(x*t) b = GF(p)(b*y) b,r,x,m = step3(b,p,r,x) return x A = {} def go1(p): X = {} for i in range(0,len(A)): X[i] = sqrt(GF(p)(A[i])) return X def go2(p): X ={} for i in range(0,len(A)): X[i] = s_root(A[i], p) return X def analyseResult(A,X,p): numberRoots = 0 for i in range(0,len(A)): x = X[i] a = A[i] if x in GF(p): if (GF(p)(x) != GF(p)(0)) & (GF(p)(x**2) != GF(p)(a)): print 'Error in implemenation' elif GF(p)(x) != GF(p)(0): numberRoots = numberRoots + 1 print 'Number of roots found:' print numberRoots n = 100 print 'Results for 128 bit prime:' p = next_prime(2^(128)) while p % 4 != 1: p = next_prime(p+1) for i in range(0,n): A[i] = GF(p).random_element() print 'Original:' time X = go1(p) analyseResult(A,X,p) print 'Tonelli:' time X = go2(p) analyseResult(A,X,p) print 'Results for 256 bit prime:' p = next_prime(2^(256)) while p % 4 != 1: p = next_prime(p+1) for i in range(0,n): A[i] = GF(p).random_element() #print 'Original:' #time X = go1(p) #analyseResult(A,X,p) print 'Tonelli:' time X = go2(p) analyseResult(A,X,p) print 'Results for 512 bit prime:' p = next_prime(2^(512)) while p % 4 != 1: p = next_prime(p+1) for i in range(0,n): A[i] = GF(p).random_element() #print 'Original:' #time X = go1(p) #analyseResult(A,X,p) print 'Tonelli:' time X = go2(p) analyseResult(A,X,p) -- Steffen --~--~---------~--~----~------------~-------~--~----~ To post to this group, send email to sage-devel@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sage-devel URLs: http://sage.scipy.org/sage/ and http://modular.math.washington.edu/sage/ -~----------~----~----~----~------~----~------~--~---