On Nov 9, 2007 11:19 PM, Steffen <[EMAIL PROTECTED]> wrote: > Hi, I have implemented the Tonelli and Shanks algorithm which has a > complexity of O(ln^4(p)) and appears to be amazing fast. So far its a
Could you post some cool impressive benchmarks? :-) william > quick and dirty implementation directly in my Sage file and without > error handling. I will ask Martin (when meeting him next time in the > office) how to integrate the implentation properly in Sage. Of course, > if somebody else does it, I am even more happy :-) Here is the current > code which returns x such that x^2 == a mod p: > > 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 = GF(17)(13) > print s_root(a,17) > > > Steffen > > > On 9 Nov., 21:50, "John Cremona" <[EMAIL PROTECTED]> wrote: > > I see. In my example a was > > > > sage: type(a) > > <type 'sage.rings.integer_mod.IntegerMod_int64'> > > > > John > > > > On 09/11/2007, Robert Bradshaw <[EMAIL PROTECTED]> wrote: > > > > > > > > > > > > > On Nov 9, 2007, at 1:43 PM, John Cremona wrote: > > > > > > [Hello Robert -- are you in Bristol yet?] > > > > > Just got in. > > > > > > I'm puzzled now. My comment on inefficiency and Steffen's were based > > > > on the code > > > >> for i from 0 <= i <= n/2: > > > >> if (i*i) % n == self.ivalue: > > > >> return self._new_c(i) > > > > > > but now when I do a.sqrt?? I do not see that code. Steffen, are you > > > > using 2.8.12? > > > > > This depends on the size of the modulus. There are three types-- > > > IntegerMod_int32, IntegerMod_int64, and IntegerMod_gmp. The 32-bit > > > one has that code, and only for small p. If your modulus is beg > > > enough, a.sqrt?? won't give you that at all. > > > > > > John > > > > > > > On 09/11/2007, Steffen <[EMAIL PROTECTED]> wrote: > > > > > >> Thx, I am wondering why I did not try the command a.sqrt?? on my own. > > > > > >> However, it seems as the implemented algorithm is not the most > > > >> efficient one. My result from a.sqrt?? from the latest release: > > > > > >> def sqrt(self, extend=True, all=False): > > > >> cdef int_fast32_t i, n = self.__modulus.int32 > > > >> if n > 100: > > > >> moduli = self._parent.factored_order() > > > >> # Unless the modulus is tiny, test to see if we're in the > > > >> really > > > >> # easy case of n prime, n = 3 mod 4. > > > >> if n > 100 and n % 4 == 3 and len(moduli) == 1 and moduli[0] > > > >> [1] == 1: > > > >> if jacobi_int(self.ivalue, self.__modulus.int32) == 1: > > > >> # it's a non-zero square, sqrt(a) = a^(p+1)/4 > > > >> i = mod_pow_int(self.ivalue, (self.__modulus.int32 > > > >> +1)/ > > > >> 4, n) > > > >> if i > n/2: > > > >> i = n-i > > > >> if all: > > > >> return [self._new_c(i), self._new_c(n-i)] > > > >> else: > > > >> return self._new_c(i) > > > >> elif self.ivalue == 0: > > > >> return self > > > >> elif not extend: > > > >> raise ValueError, "self must be a square" > > > >> # Now we use a heuristic to guess whether or not it will > > > >> # be faster to just brute-force search for squares in a c > > > >> loop... > > > >> # TODO: more tuning? > > > >> elif n <= 100 or n / (1 << len(moduli)) < 5000: > > > >> if all: > > > >> return [self._new_c(i) for i from 0 <= i < n if (i*i) > > > >> % n == self.ivalue] > > > >> else: > > > >> for i from 0 <= i <= n/2: > > > >> if (i*i) % n == self.ivalue: > > > >> return self._new_c(i) > > > >> if not extend: > > > >> raise ValueError, "self must be a square" > > > >> # Either it failed but extend was True, or the generic > > > >> algorithm is better > > > >> return IntegerMod_abstract.sqrt(self, extend=extend, all=all) > > > > > >> The easier %4 == 3 case seems to be implemented efficiently, but the > > > >> %4 == 1 not. The algo from Tonelli and Shanks might be a good > > > >> solution > > > >> here. Any thoughts on other/better algorithm? > > > > > >> Steffen > > > > > >> On 9 Nov., 18:24, "John Cremona" <[EMAIL PROTECTED]> wrote: > > > >>> Use the ?? operator to see the algorithm: > > > > > >>> sage: a=GF(next_prime(10^6)).random_element()^2; > > > >>> sage: a.sqrt?? > > > > > >>> Type: builtin_function_or_method > > > >>> Base Class: <type 'builtin_function_or_method'> > > > >>> String Form: <built-in method sqrt of > > > >>> sage.rings.integer_mod.IntegerMod_int64 object at 0x99055a4> > > > >>> Namespace: Interactive > > > >>> Source: > > > >>> def sqrt(self, extend=True, all=False): > > > >>> r""" > > > >>> Returns square root or square roots of self modulo n. > > > > > >>> INPUT: > > > >>> extend -- bool (default: True); if True, return a square > > > >>> root in an extension ring, if necessary. Otherwise, > > > >>> raise a ValueError if the square is not in the > > > >>> base ring. > > > >>> all -- bool (default: False); if True, return *all* > > > >>> square > > > >>> roots of self, instead of just one. > > > > > >>> ALGORITHM: Calculates the square roots mod $p$ for each > > > >>> of the > > > >>> primes $p$ dividing the order of the ring, then lifts them > > > >>> p-adically and uses the CRT to find a square root mod $n$. > > > > > >>> See also \code{square_root_mod_prime_power} and > > > >>> \code{square_root_mod_prime} (in this module) for more > > > >>> algorithmic details. > > > > > >>> EXAMPLES: > > > >>> sage: mod(-1, 17).sqrt() > > > >>> 4 > > > >>> sage: mod(5, 389).sqrt() > > > >>> 86 > > > >>> sage: mod(7, 18).sqrt() > > > >>> 5 > > > >>> sage: a = mod(14, 5^60).sqrt() > > > >>> sage: a*a > > > >>> 14 > > > >>> sage: mod(15, 389).sqrt(extend=False) > > > >>> Traceback (most recent call last): > > > >>> ... > > > >>> ValueError: self must be a square > > > >>> sage: Mod(1/9, next_prime(2^40)).sqrt()^(-2) > > > >>> 9 > > > >>> sage: Mod(1/25, next_prime(2^90)).sqrt()^(-2) > > > >>> 25 > > > > > >>> sage: a = Mod(3,5); a > > > >>> 3 > > > >>> sage: x = Mod(-1, 360) > > > >>> sage: x.sqrt(extend=False) > > > >>> Traceback (most recent call last): > > > >>> ... > > > >>> ValueError: self must be a square > > > >>> sage: y = x.sqrt(); y > > > >>> sqrt359 > > > >>> sage: y.parent() > > > >>> Univariate Quotient Polynomial Ring in sqrt359 over Ring > > > >>> of integers modulo 360 with modulus x^2 + 1 > > > >>> sage: y^2 > > > >>> 359 > > > > > >>> We compute all square roots in several cases: > > > >>> sage: R = Integers(5*2^3*3^2); R > > > >>> Ring of integers modulo 360 > > > >>> sage: R(40).sqrt(all=True) > > > >>> [20, 160, 200, 340] > > > >>> sage: [x for x in R if x^2 == 40] # Brute force > > > >>> verification > > > >>> [20, 160, 200, 340] > > > >>> sage: R(1).sqrt(all=True) > > > >>> [1, 19, 71, 89, 91, 109, 161, 179, 181, 199, 251, 269, > > > >>> 271, 289, 341, 359] > > > >>> sage: R(0).sqrt(all=True) > > > >>> [0, 60, 120, 180, 240, 300] > > > > > >>> sage: R = Integers(5*13^3*37); R > > > >>> Ring of integers modulo 406445 > > > >>> sage: v = R(-1).sqrt(all=True); v > > > >>> [78853, 111808, 160142, 193097, 213348, 246303, > > > >>> 294637, 327592] > > > >>> sage: [x^2 for x in v] > > > >>> [406444, 406444, 406444, 406444, 406444, 406444, > > > >>> 406444, 406444] > > > >>> sage: v = R(169).sqrt(all=True); min(v), -max(v), len(v) > > > >>> (13, 13, 104) > > > >>> sage: all([x^2==169 for x in v]) > > > >>> True > > > > > >>> Modulo a power of 2: > > > >>> sage: R = Integers(2^7); R > > > >>> Ring of integers modulo 128 > > > >>> sage: a = R(17) > > > >>> sage: a.sqrt() > > > >>> 23 > > > >>> sage: a.sqrt(all=True) > > > >>> [23, 41, 87, 105] > > > >>> sage: [x for x in R if x^2==17] > > > >>> [23, 41, 87, 105] > > > > > >>> """ > > > >>> if self.is_one(): > > > >>> if all: > > > >>> return list(self.parent().square_roots_of_one()) > > > >>> else: > > > >>> return self > > > > > >>> if not self.is_square_c(): > > > >>> if extend: > > > > > >>> and so on! > > > > > >>> John > > > > > >>> On 09/11/2007, Steffen <[EMAIL PROTECTED]> wrote: > > > > > >>>> Hi, I need to find square roots in GF(prime). I did it like this: > > > > > >>>> y = sqrt(GF(prime)(ySquare)) > > > > > >>>> So far I am not quite happy with the calculation periods and I > > > >>>> would > > > >>>> like to know which algorithm is used. In my case is prime % 4 == 1, > > > >>>> which is the hardest case to find the square root mod p. I am sage > > > >>>> newbie and probably its again only a command that I cant find. I > > > >>>> tried > > > >>>> sqrt? and similar things, but only got the information that sqrt > > > >>>> is a > > > >>>> symbolic function. Could somebody tell me which algo is > > > >>>> implemented or > > > >>>> better how to find the implemented algo. > > > > > >>>> Cheers, Steffen > > > > > >>> -- > > > >>> John Cremona > > > > > > -- > > > > John Cremona > > > > -- > > John Cremona > > > > > -- William Stein Associate Professor of Mathematics University of Washington http://wstein.org --~--~---------~--~----~------------~-------~--~----~ 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/ -~----------~----~----~----~------~----~------~--~---