# HG changeset patch
# User Martin Albrecht <malb@informatik.uni-bremen.de>
# Date 1234955738 0
# Node ID 63290203af4334a5e3cfa6a5e85d79aa26080f27
# Parent  1c1068174200edd1382394c6e7032957a7a875f8
addressed reviewers comments:
 * {{{sage: S(long(7)) works now}}}
 * vector is imported from correct place now
 * TypeError string depends on the length of X, lets see if that gets a positive review
 * added a missing {{{r"""}}}
 * function {{{def inversion_polynomials_single_sbox(self, x=None, w=None, biaffine_only=None, correct_only=None, groebner=False)}}} has one more test (most options are ignored anyway)
 * variety() is printed nicer in doctest

diff -r 1c1068174200 -r 63290203af43 sage/crypto/mq/sbox.py
--- a/sage/crypto/mq/sbox.py	Fri Feb 13 20:40:14 2009 +0000
+++ b/sage/crypto/mq/sbox.py	Wed Feb 18 11:15:38 2009 +0000
@@ -215,7 +215,8 @@
         INPUT:
             X -- either an integer, a tuple of GF(2) elements of
                  length \code{len(self)} or a finite field element in
-                 GF($2^n$)
+                 GF($2^n$). As a last resort this function tries to
+                 convert X to an integer.
 
         EXAMPLE:
             sage: S = mq.SBox([7,6,0,4,2,5,1,3])
@@ -234,14 +235,30 @@
             sage: k.<a> = GF(2^3)
             sage: S(a^2)
             a
+
+            sage: S(QQ(3))
+            4
+
+            sage: S([1]*10^6)
+            Traceback (most recent call last):
+            ...
+            TypeError: Cannot apply SBox to provided element.
+
+            sage: S(1/2)
+            Traceback (most recent call last):
+            ...
+            TypeError: Cannot apply SBox to 1/2.
         """
-        if isinstance(X, (int, Integer)):
+        if isinstance(X, (int, long, Integer)):
             return self._S[ZZ(X)]
+
         try:
-            from sage.all import vector
+            from sage.modules.free_module_element import vector
             K = X.parent()
             if K.order() == 2**self.n:
                 X = vector(X)
+            else:
+                raise TypeError
             if not self._big_endian:
                 X = list(reversed(X))
             else:
@@ -251,16 +268,28 @@
             if self._big_endian:
                 out = list(reversed(out))
             return K(vector(GF(2),out))
-        except AttributeError:
+        except (AttributeError, TypeError):
             pass
 
-        if len(X) == self.n:
-            if self._big_endian:
-                X = list(reversed(X))
-            X = ZZ(map(ZZ,X),2)
-            out =  self._S[X]
-            return self.to_bits(out)
-        raise TypeError, "Cannot apply SBox to %s"%X
+        try:
+            if len(X) == self.n:
+                if self._big_endian:
+                    X = list(reversed(X))
+                X = ZZ(map(ZZ,X),2)
+                out =  self._S[X]
+                return self.to_bits(out)
+        except TypeError:
+            pass
+
+        try:
+            return self._S[ZZ(X)]
+        except TypeError:
+            pass
+
+        if len(str(X)) > 50:
+            raise TypeError, "Cannot apply SBox to provided element."
+        else:
+            raise TypeError, "Cannot apply SBox to %s."%X
 
     def __getitem__(self, X):
         r"""
diff -r 1c1068174200 -r 63290203af43 sage/crypto/mq/sr.py
--- a/sage/crypto/mq/sr.py	Fri Feb 13 20:40:14 2009 +0000
+++ b/sage/crypto/mq/sr.py	Wed Feb 18 11:15:38 2009 +0000
@@ -105,9 +105,51 @@
 All solutions can easily be recovered using the variety function for ideals.
 
    sage: I = F.ideal()
-   sage: I.variety() # order is random-ish
-   [{k100: 0, k003: 0, k002: 1, k001: 0, k000: 0, s003: 1, s002: 0, s001: 0, s000: 1, w103: 1, w102: 1, w101: 0, w100: 0, x103: 0, x102: 1, x101: 1, x100: 1, k103: 0, k102: 0, k101: 1}, 
-    {k100: 0, k003: 1, k002: 1, k001: 0, k000: 0, s003: 0, s002: 1, s001: 1, s000: 1, w103: 0, w102: 1, w101: 0, w100: 0, x103: 1, x102: 0, x101: 0, x100: 1, k103: 1, k102: 0, k101: 1}]
+   sage: for V in I.variety():
+   ...    for k,v in sorted(V.iteritems()):
+   ...       print k,v
+   ...    print 
+   k003 0
+   k002 1
+   k001 0
+   k000 0
+   s003 1
+   s002 0
+   s001 0
+   s000 1
+   w103 1
+   w102 1
+   w101 0
+   w100 0
+   x103 0
+   x102 1
+   x101 1
+   x100 1
+   k103 0
+   k102 0
+   k101 1
+   k100 0
+   <BLANKLINE>
+   k003 1
+   k002 1
+   k001 0
+   k000 0
+   s003 0
+   s002 1
+   s001 1
+   s000 1
+   w103 0
+   w102 1
+   w101 0
+   w100 0
+   x103 1
+   x102 0
+   x101 0
+   x100 1
+   k103 1
+   k102 0
+   k101 1
+   k100 0
 
 Note that the SBox object for SR can be constructed with a call to
 \code{sr.sbox()}.
@@ -1448,7 +1490,7 @@
         return [gd[e] for e in self.varstrs(name, nr, rc, e)]
 
     def variable_dict(self):
-        """
+        r"""
         Return a dictionary to access variables in \code{self.R} by
         their names.
 
@@ -2869,8 +2911,8 @@
         INPUT:
             x -- output variables (default: None)
             w -- input variables  (default: None)
-            biaffine_only -- ignored
-            correct_only -- always True
+            biaffine_only -- ignored (always False)
+            correct_only -- ignored (always True)
             groebner -- precompute the Groebner basis for this S-Box (default: False).
 
         EXAMPLES:
@@ -2884,6 +2926,32 @@
              x1 + w0*w1*w3 + w0*w3 + w0 + w1*w3 + w1 + w2*w3, 
              x2 + w0*w2*w3 + w0*w2 + w0 + w1*w2 + w1*w3 + w2*w3, 
              x3 + w0*w1*w2 + w0 + w1*w2*w3 + w1*w2 + w1*w3 + w1 + w2 + w3]
+
+            sage: from sage.crypto.mq.sr import SR_gf2_2
+            sage: e = 4
+            sage: sr = SR_gf2_2(1, 1, 1, e)
+            sage: sr.inversion_polynomials_single_sbox()
+            [w3*w1 + w3*w0 + w3*x2 + w3*x1 + w3 + w2*w1 + w1 + x3 + x2 + x1, 
+             w3*w2 + w3*w1 + w3*x3 + w2 + w1 + x3, 
+             w3*w2 + w3*w1 + w3*x2 + w3 + w2*x3 + x2 + x1, 
+             w3*w2 + w3*w1 + w3*x3 + w3*x2 + w3*x1 + w3 + w2*x2 + w0 + x3 + x2 + x1 + x0, 
+             w3*w2 + w3*w1 + w3*x1 + w3*x0 + w2*x1 + w0 + x3 + x0, 
+             w3*w2 + w3*w1 + w3*w0 + w3*x2 + w3*x1 + w2*w0 + w2*x0 + w0 + x3 + x2 + x1 + x0, 
+             w3*w2 + w3*x1 + w3 + w2*w0 + w1*w0 + w1 + x3 + x2, 
+             w3*w2 + w3*w1 + w3*x1 + w1*x3 + x3 + x2 + x1, 
+             w3*x3 + w3*x2 + w3*x0 + w3 + w1*x2 + w1 + w0 + x2 + x0, 
+             w3*w2 + w3*w1 + w3*x2 + w3*x1 + w1*x1 + w1 + w0 + x2 + x0, 
+             w3*w2 + w3*w1 + w3*w0 + w3*x3 + w3*x1 + w2*w0 + w1*x0 + x3 + x2, 
+             w3*w2 + w3*w1 + w3*x2 + w3*x1 + w3*x0 + w3 + w1 + w0*x3 + x3 + x2, 
+             w3*w2 + w3*w1 + w3*w0 + w3*x3 + w3 + w2*w0 + w1 + w0*x2 + x3 + x2, 
+             w3*w0 + w3*x2 + w2*w0 + w0*x1 + w0 + x3 + x1 + x0, 
+             w3*w0 + w3*x3 + w3*x0 + w2*w0 + w1 + w0*x0 + w0 + x3 + x2, 
+             w3*w2 + w3 + w1 + x3*x2 + x3 + x1, 
+             w3*w2 + w3*x3 + w1 + x3*x1 + x3 + x2, 
+             w3*w2 + w3*w0 + w3*x3 + w3*x2 + w3*x1 + w0 + x3*x0 + x1 + x0, 
+             w3*w2 + w3*w1 + w3*w0 + w3*x3 + w1 + w0 + x2*x1 + x2 + x0, 
+             w3*w2 + w2*w0 + w1 + x3 + x2*x0, 
+             w3*x3 + w3*x1 + w2*w0 + w1 + x3 + x2 + x1*x0 + x1]
        """
         e = self.e
         if x is None and w is None:
