def cmp_ir(self,z):
     """ 
     returns -1 for left, 0 for in, and 1 for right from initial region
     cut line is on the north ray from L.
     """
     L = self.L
     x0 = self.x0
     if x0 > 0.5:
         if real(z) > real(L) and abs(z) < abs(L):
             return 0
         if real(z) < real(L):
             return -1
         if real(z) > real(L):
             return 1
     else:
         if imag(z) > imag(L):
             if real(z) > real(L):
                 return 1
             if real(z) < real(L):
                 return -1
         if real(z) < real(L) and real(z) > log(real(L)) + log(sqrt(1+tan(imag(z))**2)):
             return 0
         if real(z) > real(L):
             return 1
         if real(z) < real(L):
             return -1
    def calc_slog(self):
        RP = FormalPowerSeriesRing(RealField(self.iprec))
        ev = self.eigenvalues
        a1 = self.coeffs_1
        N = self.N

        #how can this be made picklable?
        class _SexpCoeffs1(FormalPowerSeries0):
            def coeffs(self,n):
               if n==0: return 0
               return sum([a1[k]*log(ev[k])**n for k in xrange(N)])/factorial(n)
        class _SexpCoeffs0(FormalPowerSeries0):
            def coeffs(self,n):
               if n==0: return 0
               return sum([a0[k]*log(ev[k])**n for k in xrange(N)])/factorial(n) 

        self.sexp_coeffs_1 = _SexpCoeffs1(RP,min_index=1)
        self.slog_coeffs_1 = self.sexp_coeffs_1.inv()

        if self.L != None:
            return self.L
        b = self.b
        iprec = self.iprec

        if b > (e**(1/e)).n(iprec):
            L = ComplexField(iprec)(0.5)
            for n in range(100):
                L = log(L)/log(b)
        else:
            L = RealField(iprec)(0)
            for n in range(100):
                L = b**L
            
        self.L = L
        return self
def bkz_runtime_k_bkz2(k, n):
    """
    Runtime estimation given ‘k‘ and assuming [CheNgu12]_ estimates are correct.
    The constants in this function were derived as follows based on Table 4 in [CheNgu12]_::
    sage: dim = [100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240,
          250]
    sage: nodes = [39.0, 44.0, 49.0, 54.0, 60.0, 66.0, 72.0, 78.0, 84.0, 96.0, 99.0, 105.0,
          111.0, 120.0, 127.0, 134.0]
    sage: times = [c + log(200,2).n() for c in nodes]
    sage: T = zip(dim, nodes)
    sage: var("a,b,c,k")
    sage: f = a*k*log(k, 2.0) + b*k + c
    sage: f = f.function(k)
    sage: f.subs(find_fit(T, f, solution_dict=True))
    k |--> 0.270188776350190*k*log(k) - 1.0192050451318417*k + 16.10253135200765
    
    .. [CheNgu12] Yuanmi Chen and Phong Q. Nguyen. BKZ 2.0: Better lattice security estimates (
        Full Version).
                  2012. http://www.di.ens.fr/~ychen/research/Full_BKZ.pdf
    """
    repeat = _sage_const_3 * log(n, _sage_const_2) - _sage_const_2 * log(
        k, _sage_const_2) + log(log(n, _sage_const_2), _sage_const_2)
    return RR(_sage_const_0p270188776350190 * k * log(k) -
              _sage_const_1p0192050451318417 * k +
              _sage_const_16p10253135200765 + repeat)
def _estimated_time(M2, M1, length, p):

    """
    Find the estimated time to extend congruences mod M1 to consistent congruences mod M2.

    INPUT:

    - ``M2`` -- an integer (the new modulus)

    - ``M1`` -- an integer (the old modulus)

    - ``length`` -- a list (the current length of the list of congruences mod ``M1``)

    - ``p`` --  a prime

    OUTPUT:

    - The estimated run time of the "CRT" step to combine consistent congruences.

    EXAMPLES::

        sage: sage.combinat.binary_recurrence_sequences._estimated_time(2**4*3**2*5*7*11*13*17, 2**4*3**2*5*7*11*13, 20, 7)
        106.211159309421

    """

    #The heuristic run time of the CRT step to go from modulus M1 to M2

    #length is the current length of cong

    Q = p * log(M2) #Size of our primes.
    NPrimes = log(M2/M1) / log(Q) #The number of primes

    return (length * (Q/p)**NPrimes).n()
示例#5
0
    def cmp_ir(self,z):
        """ 
        returns -1 for left, 0 for in, and 1 for right from initial region
        cut line is on the north ray from pfp.

        Works only for real x0.
        """
        pfp = self.pfp
        x0 = self.x0
        if x0 > 0.5:
            print z,abs(z)
            if real(z) >= real(pfp) and abs(z) < abs(pfp):
                return 0
            if real(z) < real(pfp):
                return -1
            if real(z) > real(pfp):
                return 1
        else:
            if imag(z) > imag(pfp):
                if real(z) > real(pfp):
                    return 1
                if real(z) < real(pfp):
                    return -1
            if real(z) < real(pfp) and real(z) > log(real(pfp)) + log(sqrt(1+tan(imag(z))**2)):
                return 0
            if real(z) > real(pfp):
                return 1
            if real(z) < real(pfp):
                return -1
def _estimated_time(M2, M1, length, p):
    """
    Find the estimated time to extend congruences mod M1 to consistent congruences mod M2.

    INPUT:

    - ``M2`` -- an integer (the new modulus)

    - ``M1`` -- an integer (the old modulus)

    - ``length`` -- a list (the current length of the list of congruences mod ``M1``)

    - ``p`` --  a prime

    OUTPUT:

    - The estimated run time of the "CRT" step to combine consistent congruences.

    EXAMPLES::

        sage: sage.combinat.binary_recurrence_sequences._estimated_time(2**4*3**2*5*7*11*13*17, 2**4*3**2*5*7*11*13, 20, 7)
        106.211159309421

    """

    #The heuristic run time of the CRT step to go from modulus M1 to M2

    #length is the current length of cong

    Q = p * log(M2)  #Size of our primes.
    NPrimes = log(M2 / M1) / log(Q)  #The number of primes

    return (length * (Q / p)**NPrimes).n()
示例#7
0
文件: lwe.py 项目: bopopescu/sage-5
    def __init__(self, n, instance='key', m=None):
        """
        Construct LWE instance parameterised by security parameter ``n`` where
        all other parameters are chosen as in [CGW13]_.

        INPUT:

        - ``n`` - security parameter (integer >= 89)
        - ``instance`` - one of

          - "key" - the LWE-instance that hides the secret key is generated
          - "encrypt" - the LWE-instance that hides the message is generated
            (default: ``key``)

        - ``m`` - number of allowed samples or ``None`` in which case ``m`` is
          chosen as in [CGW13_].  (default: ``None``)

        EXAMPLES::

            sage: from sage.crypto.lwe import UniformNoiseLWE
            sage: UniformNoiseLWE(89)
            LWE(89, 154262477, UniformSampler(0, 351), 'noise', 131)

            sage: UniformNoiseLWE(89, instance='encrypt')
            LWE(131, 154262477, UniformSampler(0, 497), 'noise', 181)
        """

        if n < 89:
            raise TypeError("Parameter too small")

        n2 = n
        C = 4 / sqrt(2 * pi)
        kk = floor((n2 - 2 * log(n2, 2)**2) / 5)
        n1 = floor((3 * n2 - 5 * kk) / 2)
        ke = floor((n1 - 2 * log(n1, 2)**2) / 5)
        l = floor((3 * n1 - 5 * ke) / 2) - n2
        sk = ceil((C * (n1 + n2))**(3 / 2))
        se = ceil((C * (n1 + n2 + l))**(3 / 2))
        q = next_prime(
            max(ceil((4 * sk)**((n1 + n2) / n1)),
                ceil((4 * se)**((n1 + n2 + l) / (n2 + l))),
                ceil(4 * (n1 + n2) * se * sk + 4 * se + 1)))

        if kk <= 0:
            raise TypeError("Parameter too small")

        if instance == 'key':
            D = UniformSampler(0, sk - 1)
            if m is None:
                m = n1
            LWE.__init__(self, n=n2, q=q, D=D, secret_dist='noise', m=m)
        elif instance == 'encrypt':
            D = UniformSampler(0, se - 1)
            if m is None:
                m = n2 + l
            LWE.__init__(self, n=n1, q=q, D=D, secret_dist='noise', m=m)
        else:
            raise TypeError("Parameter instance=%s not understood." %
                            (instance))
def strain_sensitivity(freq):
    r"""
    Return LISA strain spectral sensitivity at a given frequency.

    The strain spectral sensitivity is the square root of the effective
    noise power spectral density (cf. :func:`power_spectral_density`).

    INPUT:

    - ``freq`` -- frequency `f` (in `\mathrm{Hz}`)

    OUTPUT:

    - strain sensitivity `S(f)^{1/2}` (in `\mathrm{Hz}^{-1/2}`)

    EXAMPLES::

        sage: from kerrgeodesic_gw import lisa_detector
        sage: hn = lisa_detector.strain_sensitivity
        sage: hn(1.e-1)  # tol 1.0e-13
        5.82615031500758e-20
        sage: hn(1.e-2)  # tol 1.0e-13
        1.654806317072275e-20
        sage: hn(1.e-3)  # tol 1.0e-13
        1.8082609253700212e-19

    ::

        sage: plot_loglog(hn, (1e-5, 1), plot_points=2000, ymin=1e-20, ymax=1e-14,
        ....:             axes_labels=[r"$f\ [\mathrm{Hz}]$",
        ....:                          r"$S(f)^{1/2} \ \left[\mathrm{Hz}^{-1/2}\right]$"],
        ....:             gridlines='minor', frame=True, axes=False)
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

        from kerrgeodesic_gw import lisa_detector
        hn = lisa_detector.strain_sensitivity
        g = plot_loglog(hn, (1e-5, 1), plot_points=2000, ymin=1e-20, ymax=1e-14, \
                        axes_labels=[r"$f\ [\mathrm{Hz}]$", \
                                     r"$S(f)^{1/2} \ \left[\mathrm{Hz}^{-1/2}\right]$"], \
                        gridlines='minor', frame=True, axes=False)
        sphinx_plot(g)

    """
    global _sensitivity_spline
    if not _sensitivity_spline:
        data = []
        file_name = os.path.join(os.path.dirname(__file__),
                                 "data/Sensitivity_LISA_SciRD1806_Alloc.dat")
        with open(file_name, "r") as data_file:
            for dline in data_file:
                f, s = dline.split('\t')
                data.append((log(RDF(f), 10), log(sqrt(RDF(s)), 10)))
        _sensitivity_spline = spline(data)
    if freq < 1.e-5 or freq > 1.:
        raise ValueError("frequency {} Hz is out of range".format(freq))
    freq = RDF(freq)
    return RDF(10)**(_sensitivity_spline(log(freq, 10)))
示例#9
0
 def calc_prec():
     if self.prec != None:
         return self.prec
     iv0 = IntuitiveAbel(self.bsym,self.N-1,iprec=self.iprec,x0=self.x0sym)
     self.iv0 = iv0
     self.err = abs(iv0.sexp(0.5) - self.sexp(0.5))
     print "err:", self.err.n(20)
     self.prec = floor(-log(self.err)/log(2.0))
示例#10
0
def discrete_curve_2(nb_equipes, max_points=100):
    r"""
    """
    from sage.misc.functional import round
    from sage.functions.log import log
    from sage.rings.integer_ring import ZZ
    f = lambda p:(max_points-1)*(1-log(p)/log(nb_equipes))+1
    L = [ZZ(round(f(p=i))) for i in range(1,nb_equipes+1)]
    return L
示例#11
0
def discrete_curve_2(nb_equipes, max_points=100):
    r"""
    """
    from sage.misc.functional import round
    from sage.functions.log import log
    from sage.rings.integer_ring import ZZ
    f = lambda p: (max_points - 1) * (1 - log(p) / log(nb_equipes)) + 1
    L = [ZZ(round(f(p=i))) for i in range(1, nb_equipes + 1)]
    return L
示例#12
0
 def _height(P, check=True):
     if check:
         assert P.curve() == self._E, "the point P must lie on the curve from which the height function was created"
     Q = n * P
     cQ = denominator(Q[0])
     uQ = self.lift(Q, prec=prec)
     si = self.__padic_sigma_square(uQ, prec=prec)
     nn = self._q.valuation()
     qEu = self._q / p ** nn
     return -(log(si*self._Csquare()/cQ) + log(uQ)**2/log(qEu)) / n**2
示例#13
0
    def newton_sqrt(self, f, x0, prec):
        r"""
        Takes the square root of the power series `f` by Newton's method

        NOTE:

        this function should eventually be moved to `p`-adic power series ring

        INPUT:

        - f power series wtih coefficients in `\QQ_p` or an extension
        - x0 seeds the Newton iteration
        - prec precision

        OUTPUT:

        the square root of `f`

        EXAMPLES::

            sage: R.<x> = QQ['x']
            sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x)
            sage: Q = H(0,0)
            sage: u,v = H.local_coord(Q,prec=100)
            sage: K = Qp(11,5)
            sage: HK = H.change_ring(K)
            sage: L.<a> = K.extension(x^20-11)
            sage: HL = H.change_ring(L)
            sage: S = HL(u(a),v(a))
            sage: f = H.hyperelliptic_polynomials()[0]
            sage: y = HK.newton_sqrt( f(u(a)^11), a^11,5)
            sage: y^2 - f(u(a)^11)
            O(a^122)

        AUTHOR:

        - Jennifer Balakrishnan

        """
        z = x0
        try:
            x = f.parent().variable_name()
            if x != 'a':  #this is to distinguish between extensions of Qp that are finite vs. not
                S = f.base_ring()[[x]]
                x = S.gen()
        except ValueError:
            pass
        z = x0
        loop_prec = (log(RR(prec)) / log(RR(2))).ceil()
        for i in range(loop_prec):
            z = (z + f / z) / 2
        try:
            return z + O(x**prec)
        except (NameError, ArithmeticError, TypeError):
            return z
示例#14
0
文件: lwe.py 项目: sagemath/sage
    def __init__(self, n, instance='key', m=None):
        """
        Construct LWE instance parameterised by security parameter ``n`` where
        all other parameters are chosen as in [CGW2013]_.

        INPUT:

        - ``n`` - security parameter (integer >= 89)
        - ``instance`` - one of

          - "key" - the LWE-instance that hides the secret key is generated
          - "encrypt" - the LWE-instance that hides the message is generated
            (default: ``key``)

        - ``m`` - number of allowed samples or ``None`` in which case ``m`` is
          chosen as in [CGW2013]_.  (default: ``None``)

        EXAMPLES::

            sage: from sage.crypto.lwe import UniformNoiseLWE
            sage: UniformNoiseLWE(89)
            LWE(89, 154262477, UniformSampler(0, 351), 'noise', 131)

            sage: UniformNoiseLWE(89, instance='encrypt')
            LWE(131, 154262477, UniformSampler(0, 497), 'noise', 181)
        """

        if n<89:
            raise TypeError("Parameter too small")

        n2 = n
        C  = 4/sqrt(2*pi)
        kk = floor((n2-2*log(n2, 2)**2)/5)
        n1 = floor((3*n2-5*kk)/2)
        ke = floor((n1-2*log(n1, 2)**2)/5)
        l  = floor((3*n1-5*ke)/2)-n2
        sk = ceil((C*(n1+n2))**(3/2))
        se = ceil((C*(n1+n2+l))**(3/2))
        q = next_prime(max(ceil((4*sk)**((n1+n2)/n1)), ceil((4*se)**((n1+n2+l)/(n2+l))), ceil(4*(n1+n2)*se*sk+4*se+1)))

        if kk<=0:
            raise TypeError("Parameter too small")

        if instance == 'key':
            D  = UniformSampler(0, sk-1)
            if m is None:
                m = n1
            LWE.__init__(self, n=n2, q=q, D=D, secret_dist='noise', m=m)
        elif instance == 'encrypt':
            D   = UniformSampler(0, se-1)
            if m is None:
                m = n2+l
            LWE.__init__(self, n=n1, q=q, D=D, secret_dist='noise', m=m)
        else:
            raise TypeError("Parameter instance=%s not understood."%(instance))
示例#15
0
    def slog(self,z,n=None):
        slog = self.slog
        b = self.b

        if n == None:
            n = self.N
        if self.cmp_ir(z) == -1:
            return slog(b**z)-1
        if self.cmp_ir(z) == +1:
            return slog(log(z)/log(b))+1
        return self.slog_1t(z)
def bkz_runtime_k_sieve(k, n):
    """
    Runtime estimation given ‘k‘ and assuming sieving is used to realise the SVP oracle.
    For small ‘k‘ we use estimates based on experiments. For ‘k ě 90‘ we use the asymptotics.
    """
    repeat = _sage_const_3 *log(n, _sage_const_2 ) - _sage_const_2 *log(k, _sage_const_2 ) + log(log(n, _sage_const_2 ), _sage_const_2 )
    if k < _sage_const_90 :
        return RR(_sage_const_0p45 *k + _sage_const_12p31 ) + repeat
    else:
        # we simply pick the same additive constant 12.31 as above
        return RR(_sage_const_0p3366 *k + _sage_const_12p31 ) + repeat
def bkz_runtime_k_sieve(k, n):
    """
    Runtime estimation given ‘k‘ and assuming sieving is used to realise the SVP oracle.
    For small ‘k‘ we use estimates based on experiments. For ‘k ě 90‘ we use the asymptotics.
    """
    repeat = _sage_const_3 * log(n, _sage_const_2) - _sage_const_2 * log(
        k, _sage_const_2) + log(log(n, _sage_const_2), _sage_const_2)
    if k < _sage_const_90:
        return RR(_sage_const_0p45 * k + _sage_const_12p31) + repeat
    else:
        # we simply pick the same additive constant 12.31 as above
        return RR(_sage_const_0p3366 * k + _sage_const_12p31) + repeat
示例#18
0
    def sexp_0(self,t):
        #convergence radius 1
        t = self._in_prec(t)
        sexp = self.sexp_0
        b = self.b

        #development point -1 convergence radius 1
        if real(t)>1:
            return b**(sexp(t-1))
        if real(t)<0:
            #sage bug, log(z,b) does not work for complex z
            return log(sexp(t+1))/log(b)
	return self.sexp_0_raw(t)
示例#19
0
    def sexp_1(self,t):
        t = self._in_prec(t)
        sexp = self.sexp_1
        b = self.b
        IM = self.IM
        N = self.N

        #development point 0 convergence radius 2
        if real(t)>1:
            return b**(sexp(t-1))
        if real(t)<0:
            #sage bug, log(z,b) does not work for complex z
            return log(sexp(t+1))/log(b)
	return self.sexp_1_raw(t)
示例#20
0
 def log(self,workprec=Infinity):
     from sage.functions.log import log
     from sage.functions.other import floor
     if workprec is Infinity:
         raise ApproximationError("unable to compute log to infinite precision")
     parent = self.parent()
     pow = parent(-1)
     res = parent(0)
     t = parent(1) - self
     iter = workprec + floor(log(workprec)/log(parent._p)) + 1
     for i in range(1,iter):
         pow *= t
         res += pow / parent(i)
         res = res.truncate(workprec)
     return res
def params_str(d, keyword_width=None):
    """
    Return string of key,value pairs as a string "key0: value0, key1: value1"
    :param d:  report dictionary
    :keyword_width:keys are printed with this width
    """
    if d is None:
        return
    s = []
    for k in d:
        v = d[k]
        if keyword_width:
            fmt = u"%%%ds" % keyword_width
            k = fmt % k
        if ZZ(_sage_const_1
              ) / _sage_const_2048 < v < _sage_const_2048 or v == _sage_const_0:
            try:
                s.append(u"%s: %9d" % (k, ZZ(v)))
            except TypeError:
                if v < _sage_const_2p0 and v >= _sage_const_0p0:
                    s.append(u"%s: %9.7f" % (k, v))
                else:
                    s.append(u"%s: %9.4f" % (k, v))
        else:
            t = u"«2^%.1f" % log(v, _sage_const_2).n()
            s.append(u"%s: %9s" % (k, t))
    return u", ".join(s)
示例#22
0
    def calc_prec(self):
        if self.prec != None:
            return self.prec

        mp0 = MatrixPowerSexp(self.bsym,self.N-1,iprec=self.iprec,x0=self.x0sym)

        sexp_precision=RR(1)*log(abs(self.sexp_1(0.5)-mp0.sexp_1(0.5)),2.0)
        self.prec = (-sexp_precision).floor()
        print "sexp precision: " , self.prec

        cprec = self.prec+ceil(log(self.N)/log(2.0))

        #self.eigenvalues = [ ev.n(cprec) for ev in self.eigenvalues ]
        #self.IM = self.IM.n(cprec)
        #self.b = self.bsym.n(cprec)
        return self
示例#23
0
    def L_invariant(self, prec=20):
        r"""
        Returns the *mysterious* `\mathcal{L}`-invariant associated
        to an elliptic curve with split multiplicative reduction.

        One
        instance where this constant appears is in the exceptional
        case of the `p`-adic Birch and Swinnerton-Dyer conjecture as
        formulated in [MTT]_. See [Col]_ for a detailed discussion.

        INPUT:

        - ``prec`` - the `p`-adic precision, default is 20.

        REFERENCES:

        [MTT]_

        .. [Col] Pierre Colmez, Invariant `\mathcal{L}` et derivees de
           valeurs propres de Frobenius, preprint, 2004.

        EXAMPLES::

            sage: eq = EllipticCurve('130a1').tate_curve(5)
            sage: eq.L_invariant(prec=10)
            5^3 + 4*5^4 + 2*5^5 + 2*5^6 + 2*5^7 + 3*5^8 + 5^9 + O(5^10)
        """
        if not self.is_split():
            raise RuntimeError("The curve must have split multiplicative "
                               "reduction")
        qE = self.parameter(prec=prec)
        n = qE.valuation()
        u = qE / self._p ** n
        # the p-adic logarithm of Iwasawa normalised by log(p) = 0
        return log(u) / n
def params_str(d, keyword_width=None):
    """
    Return string of key,value pairs as a string "key0: value0, key1: value1"
    :param d:  report dictionary
    :keyword_width:keys are printed with this width
    """
    if d is None:
        return
    s = []
    for k in d:
        v = d[k]
        if keyword_width:
            fmt = u"%%%ds" % keyword_width
            k = fmt % k
        if ZZ(_sage_const_1 )/_sage_const_2048  < v < _sage_const_2048  or v == _sage_const_0 :
            try:
                s.append(u"%s: %9d" % (k, ZZ(v)))
            except TypeError:
                if v < _sage_const_2p0  and v >= _sage_const_0p0 :
                    s.append(u"%s: %9.7f" % (k, v))
                else:
                    s.append(u"%s: %9.4f" % (k, v))
        else:
            t = u"«2^%.1f" % log(v, _sage_const_2 ).n()
            s.append(u"%s: %9s" % (k, t))
    return u", ".join(s)
示例#25
0
    def L_invariant(self, prec=20):
        r"""
        Returns the *mysterious* `\mathcal{L}`-invariant associated
        to an elliptic curve with split multiplicative reduction.

        One
        instance where this constant appears is in the exceptional
        case of the `p`-adic Birch and Swinnerton-Dyer conjecture as
        formulated in [MTT]_. See [Col]_ for a detailed discussion.

        INPUT:

        - ``prec`` - the `p`-adic precision, default is 20.

        REFERENCES:

        [MTT]_

        .. [Col] Pierre Colmez, Invariant `\mathcal{L}` et derivees de
           valeurs propres de Frobenius, preprint, 2004.

        EXAMPLES::

            sage: eq = EllipticCurve('130a1').tate_curve(5)
            sage: eq.L_invariant(prec=10)
            5^3 + 4*5^4 + 2*5^5 + 2*5^6 + 2*5^7 + 3*5^8 + 5^9 + O(5^10)
        """
        if not self.is_split():
            raise RuntimeError("The curve must have split multiplicative "
                               "reduction")
        qE = self.parameter(prec=prec)
        n = qE.valuation()
        u = qE / self._p**n
        # the p-adic logarithm of Iwasawa normalised by log(p) = 0
        return log(u) / n
示例#26
0
    def Dini(a=1, b=1, name="Dini's surface"):
        r"""
        Returns Dini's surface, with parametrization

        .. MATH::

            \begin{aligned}
              x(u, v) & = a \cos(u)\sin(v); \\
              y(u, v) & = a \sin(u)\sin(v); \\
              z(u, v) & = u + \log(\tan(v/2)) + \cos(v).
            \end{aligned}

        INPUT:

        - ``a, b`` -- surface parameters.

        - ``name`` -- string. Name of the surface.

        EXAMPLES::

            sage: dini = surfaces.Dini(a=3, b=4); dini
            Parametrized surface ('Dini's surface') with equation (3*cos(u)*sin(v), 3*sin(u)*sin(v), 4*u + 3*cos(v) + 3*log(tan(1/2*v)))
            sage: dini.plot()  # not tested -- known bug (see #10132)

        """

        u, v = var("u, v")
        dini_eq = [a * cos(u) * sin(v), a * sin(u) * sin(v), a * (cos(v) + log(tan(v / 2))) + b * u]
        coords = ((u, 0, 2 * pi), (v, 0, 2 * pi))

        return ParametrizedSurface3D(dini_eq, coords, name)
示例#27
0
    def Dini(a=1, b=1, name="Dini's surface"):
        r"""
        Return Dini's surface, with parametrization

        .. MATH::

            \begin{aligned}
              x(u, v) & = a \cos(u)\sin(v); \\
              y(u, v) & = a \sin(u)\sin(v); \\
              z(u, v) & = u + \log(\tan(v/2)) + \cos(v).
            \end{aligned}

        INPUT:

        - ``a, b`` -- surface parameters.

        - ``name`` -- string. Name of the surface.

        For more information, see :wikipedia:`Dini%27s_surface`.

        EXAMPLES::

            sage: dini = surfaces.Dini(a=3, b=4); dini
            Parametrized surface ('Dini's surface') with equation (3*cos(u)*sin(v), 3*sin(u)*sin(v), 4*u + 3*cos(v) + 3*log(tan(1/2*v)))
            sage: dini.plot()
            Graphics3d Object
        """
        u, v = var('u, v')
        dini_eq = [
            a * cos(u) * sin(v), a * sin(u) * sin(v),
            a * (cos(v) + log(tan(v / 2))) + b * u
        ]
        coords = ((u, 0, 2 * pi), (v, 0, 2 * pi))
        return ParametrizedSurface3D(dini_eq, coords, name)
示例#28
0
def _prec_for_solve_diff_eqn_families(M, p):
    #UPDATE THIS with valuation of K[0]-1 and K[1]
    r"""
        A helper function for determining the (relative) precision of the input
        to solve_diff_eqn required in order obtain an answer with (relative)
        precision ``M``. The parameter ``p`` is the prime and ``k`` is the weight.

        Given input precision `M_\text{in}`, the output has precision

        .. MATH::

            M = M_\text{in} - \lceil\log_p(M_\text{in}) - 3.

    """
    # Do we need the weight?
    # A good guess to begin:
    if M < 1:
        raise ValueError("Desired precision M(=%s) must be at least 1."%(M))
    cp = (p - 2) / (p - 1)
    Min = ZZ(3 + M + ceil(ZZ(M).log(p)))
    # It looks like usually there are no iterations
    # For low M, there can be 1 or 2
    while M > Min*cp - ceil(log((Min * cp),p)) - 3: #THINK ABOUT THIS MORE
        Min += 1
        #print("An iteration in _prec_solve_diff_eqn")
    return Min
示例#29
0
    def Dini(a=1, b=1, name="Dini's surface"):
        r"""
        Returns Dini's surface, with parametrization

        .. MATH::

            \begin{aligned}
              x(u, v) & = a \cos(u)\sin(v); \\
              y(u, v) & = a \sin(u)\sin(v); \\
              z(u, v) & = u + \log(\tan(v/2)) + \cos(v).
            \end{aligned}

        INPUT:

        - ``a, b`` -- surface parameters.

        - ``name`` -- string. Name of the surface.

        EXAMPLES::

            sage: dini = surfaces.Dini(a=3, b=4); dini
            Parametrized surface ('Dini's surface') with equation (3*cos(u)*sin(v), 3*sin(u)*sin(v), 4*u + 3*cos(v) + 3*log(tan(1/2*v)))
            sage: dini.plot()  # not tested -- known bug (see #10132)

        """

        u, v = var('u, v')
        dini_eq = [a*cos(u)*sin(v), a*sin(u)*sin(v),
                   a*(cos(v) + log(tan(v/2))) + b*u]
        coords = ((u, 0, 2*pi), (v, 0, 2*pi))


        return ParametrizedSurface3D(dini_eq, coords, name)
示例#30
0
def error_function(model, N, x0):
    """
    Compute the error function of a truncated ODE.

    INPUT:

    - ``model`` -- Polynomial ODE or string containing the model in text format

    - ``N`` -- integer; truncation order

    - ``x0`` -- list; initial point

    OUTPUT:

    - ``Ts`` -- convergence time computed from the reduced quadratic system

    - ``error`` -- function of `t`, the estimated truncation error in the supremum norm

    EXAMPLES::

        sage: from carlin.transformation import error_function
        sage: from carlin.library import quadratic_scalar as P
        sage: Ts, error = error_function(P(0.5, 2), 2, [0, 0.5])
        sage: Ts
        0.8109...
        sage: error
        0.5*(2.0*e^(0.5*t) - 2.0)^2*e^(0.5*t)/(-2.0*e^(0.5*t) + 3.0)
    """
    from numpy.linalg import norm
    from sage.symbolic.ring import SR

    if isinstance(model, str):
        [F, n, k] = get_Fj_from_model(model)
    elif isinstance(model, PolynomialODE):
        [F, n, k] = get_Fj_from_model(model.funcs(), model.dim(),
                                      model.degree())

    [Fquad, nquad, kquad] = quadratic_reduction(F, n, k)

    ch = characteristics(Fquad, nquad, kquad)

    norm_F1_tilde, norm_F2_tilde = ch['norm_Fi_inf']

    x0_hat = [kron_power(x0, i + 1) for i in range(k - 1)]

    #transform to flat list
    x0_hat = [item for sublist in x0_hat for item in sublist]

    norm_x0_hat = norm(x0_hat, ord=inf)
    beta0 = ch['beta0_const'] * norm_x0_hat
    Ts = 1 / norm_F1_tilde * log(1 + 1 / beta0)

    t = SR.var('t')
    error = norm_x0_hat * exp(
        norm_F1_tilde * t) / (1 + beta0 - beta0 * exp(norm_F1_tilde * t)) * (
            beta0 * (exp(norm_F1_tilde * t) - 1))**N
    return [Ts, error]
示例#31
0
    def super(self,x):
        """
        Development point is x0-1
        """
        if isinstance(x,float) and self.iprec != None:
           x = RealField(self.iprec)(x)
            
        super = self.super
        super_raw = self.super_raw
        b = self.b
        c = self.c

        xt = x - c
        if real(xt)<-0.5:
            return log(super(x+1))/log(b)
        if real(xt)>0.5:
            return b**(super(x-1))
        return super_raw(x)
示例#32
0
 def calc_prec(self):
     if self.prec != None:
         return self.prec
     iv0 = IntuitiveTetration(self.bsym,self.N-1,iprec=self.iprec,x0=self.x0sym)
     self.iv0 = iv0
     d = lambda x: self.slog(x) - iv0.slog(x)
     maximum = find_maximum_on_interval(d,0,1,maxfun=20)
     minimum = find_minimum_on_interval(d,0,1,maxfun=20)
     print "max:", maximum[0].n(20), 'at:', maximum[1]
     print "min:", minimum[0].n(20), 'at:', minimum[1]
     self.err = max( abs(maximum[0]), abs(minimum[0]))
     print "slog err:", self.err.n(20)
     self.prec = floor(-self.err.log(2))
     
     self.sexp_err = abs(iv0.sexp(0.5) - self.sexp(0.5))
     print "sexp err:", self.sexp_err.n(20)
     self.sexp_prec = floor(-log(self.sexp_err)/log(2.0))
     return self
示例#33
0
 def _height(P, check=True):
     if check:
         assert P.curve(
         ) == self._E, "the point P must lie on the curve from which the height function was created"
     Q = n * P
     cQ = denominator(Q[0])
     q = self.parameter(prec=prec)
     nn = q.valuation()
     precp = prec + nn + 2
     uQ = self.lift(Q, prec=precp)
     si = self.__padic_sigma_square(uQ, prec=precp)
     q = self.parameter(prec=precp)
     nn = q.valuation()
     qEu = q / p**nn
     res = -(log(si * self._Csquare(prec=precp) / cQ) +
             log(uQ)**2 / log(qEu)) / n**2
     R = Qp(self._p, prec)
     return R(res)
示例#34
0
        def _find_N_43():
            """
            Find the precision used for thm 4.3 in Goncalves
            for p >> 0, N = N0 + 2
            """
            p = self._p
            r = self._r
            d = self._d
            delta = self._delta
            N0 = self._N0
            left_side = N0 + floor(log((d * p * (r - 1) + r) / delta) / log(p))

            def right_side_log(n):
                return floor(log(p * (r * n - 1) - r) / log(p))

            n = left_side
            while n <= left_side + right_side_log(n):
                n += 1
            return n
示例#35
0
文件: lwe.py 项目: bopopescu/sage-5
    def __init__(self, N, delta=0.01, m=None):
        """
        Construct a Ring-LWE oracle in dimension ``n=phi(N)`` where
        the modulus ``q`` and the ``stddev`` of the noise is chosen as in
        [LP11]_.

        INPUT:

        - ``N`` - index of cyclotomic polynomial (integer > 0, must be power of 2)
        - ``delta`` - error probability per symbol (default: 0.01)
        - ``m`` - number of allowed samples or ``None`` in which case ``3*n`` is
          used (default: ``None``)

        EXAMPLES::

            sage: from sage.crypto.lwe import RingLindnerPeikert
            sage: RingLindnerPeikert(N=16)
            RingLWE(16, 1031, DiscreteGaussianPolynomialSamplerRejection(8, 2.803372, 53, 4), x^8 + 1, 'noise', 24)
        """
        n = euler_phi(N)
        if m is None:
            m = 3 * n
        # Find c>=1 such that c*exp((1-c**2)/2))**(2*n) == 2**-40
        #  i.e c>=1 such that 2*n*log(c)+n*(1-c**2) + 40*log(2) == 0
        c = var('c')
        c = find_root(2 * n * log(c) + n * (1 - c**2) + 40 * log(2) == 0, 1,
                      10)
        # Upper bound on s**2/t
        s_t_bound = (sqrt(2) * pi / c / sqrt(2 * n * log(2 / delta))).n()
        # Interpretation of "choose q just large enough to allow for a Gaussian parameter s>=8" in [LP11]_
        q = next_prime(floor(2**round(log(256 / s_t_bound, 2))))
        # Gaussian parameter as defined in [LP11]_
        s = sqrt(s_t_bound * floor(q / 4))
        # Transform s into stddev
        stddev = s / sqrt(2 * pi.n())
        D = DiscreteGaussianPolynomialSampler(n, stddev)
        RingLWE.__init__(self,
                         N=N,
                         q=q,
                         D=D,
                         poly=None,
                         secret_dist='noise',
                         m=m)
示例#36
0
文件: lwe.py 项目: bopopescu/sage-5
    def __init__(self, n, delta=0.01, m=None):
        """
        Construct LWE instance parameterised by security parameter ``n`` where
        the modulus ``q`` and the ``stddev`` of the noise is chosen as in
        [LP11]_.

        INPUT:

        - ``n`` - security parameter (integer > 0)
        - ``delta`` - error probability per symbol (default: 0.01)
        - ``m`` - number of allowed samples or ``None`` in which case ``m=2*n +
          128`` as in [LP11]_ (default: ``None``)

        EXAMPLES::

            sage: from sage.crypto.lwe import LindnerPeikert
            sage: LindnerPeikert(n=20)
            LWE(20, 2053, DiscreteGaussianSamplerRejection(3.600954, 53, 4), 'noise', 168)
        """
        if m is None:
            m = 2 * n + 128
        # Find c>=1 such that c*exp((1-c**2)/2))**(2*n) == 2**-40
        #         (c*exp((1-c**2)/2))**(2*n) == 2**-40
        #    log((c*exp((1-c**2)/2))**(2*n)) == -40*log(2)
        #       (2*n)*log(c*exp((1-c**2)/2)) == -40*log(2)
        #  2*n*(log(c)+log(exp((1-c**2)/2))) == -40*log(2)
        #            2*n*(log(c)+(1-c**2)/2) == -40*log(2)
        #              2*n*log(c)+n*(1-c**2) == -40*log(2)
        #  2*n*log(c)+n*(1-c**2) + 40*log(2) == 0
        c = var('c')
        c = find_root(2 * n * log(c) + n * (1 - c**2) + 40 * log(2) == 0, 1,
                      10)
        # Upper bound on s**2/t
        s_t_bound = (sqrt(2) * pi / c / sqrt(2 * n * log(2 / delta))).n()
        # Interpretation of "choose q just large enough to allow for a Gaussian parameter s>=8" in [LP11]_
        q = next_prime(floor(2**round(log(256 / s_t_bound, 2))))
        # Gaussian parameter as defined in [LP11]_
        s = sqrt(s_t_bound * floor(q / 4))
        # Transform s into stddev
        stddev = s / sqrt(2 * pi.n())
        D = DiscreteGaussianSampler(stddev)
        LWE.__init__(self, n=n, q=q, D=D, secret_dist='noise', m=m)
    def newton_sqrt(self, f, x0, prec):
        r"""
        Takes the square root of the power series `f` by Newton's method

        NOTE:

        this function should eventually be moved to `p`-adic power series ring

        INPUT:

        - ``f`` -- power series with coefficients in `\QQ_p` or an extension
        - ``x0`` -- seeds the Newton iteration
        - ``prec`` -- precision

        OUTPUT: the square root of `f`

        EXAMPLES::

            sage: R.<x> = QQ['x']
            sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x)
            sage: Q = H(0,0)
            sage: u,v = H.local_coord(Q,prec=100)
            sage: K = Qp(11,5)
            sage: HK = H.change_ring(K)
            sage: L.<a> = K.extension(x^20-11)
            sage: HL = H.change_ring(L)
            sage: S = HL(u(a),v(a))
            sage: f = H.hyperelliptic_polynomials()[0]
            sage: y = HK.newton_sqrt( f(u(a)^11), a^11,5)
            sage: y^2 - f(u(a)^11)
            O(a^122)

        AUTHOR:

        - Jennifer Balakrishnan
        """
        z = x0
        loop_prec = (log(RR(prec)) / log(RR(2))).ceil()
        for i in range(loop_prec):
            z = (z + f / z) / 2
        return z
示例#38
0
文件: lwe.py 项目: sagemath/sage
    def __init__(self, n, delta=0.01, m=None):
        """
        Construct LWE instance parameterised by security parameter ``n`` where
        the modulus ``q`` and the ``stddev`` of the noise is chosen as in
        [LP2011]_.

        INPUT:

        - ``n`` - security parameter (integer > 0)
        - ``delta`` - error probability per symbol (default: 0.01)
        - ``m`` - number of allowed samples or ``None`` in which case ``m=2*n +
          128`` as in [LP2011]_ (default: ``None``)

        EXAMPLES::

            sage: from sage.crypto.lwe import LindnerPeikert
            sage: LindnerPeikert(n=20)
            LWE(20, 2053, Discrete Gaussian sampler over the Integers with sigma = 3.600954 and c = 0, 'noise', 168)
        """
        if m is None:
            m = 2*n + 128
        # Find c>=1 such that c*exp((1-c**2)/2))**(2*n) == 2**-40
        #         (c*exp((1-c**2)/2))**(2*n) == 2**-40
        #    log((c*exp((1-c**2)/2))**(2*n)) == -40*log(2)
        #       (2*n)*log(c*exp((1-c**2)/2)) == -40*log(2)
        #  2*n*(log(c)+log(exp((1-c**2)/2))) == -40*log(2)
        #            2*n*(log(c)+(1-c**2)/2) == -40*log(2)
        #              2*n*log(c)+n*(1-c**2) == -40*log(2)
        #  2*n*log(c)+n*(1-c**2) + 40*log(2) == 0
        c = SR.var('c')
        c = find_root(2*n*log(c)+n*(1-c**2) + 40*log(2) == 0, 1, 10)
        # Upper bound on s**2/t
        s_t_bound = (sqrt(2) * pi / c / sqrt(2*n*log(2/delta))).n()
        # Interpretation of "choose q just large enough to allow for a Gaussian parameter s>=8" in [LP2011]_
        q = next_prime(floor(2**round(log(256 / s_t_bound, 2))))
        # Gaussian parameter as defined in [LP2011]_
        s = sqrt(s_t_bound*floor(q/4))
        # Transform s into stddev
        stddev = s/sqrt(2*pi.n())
        D   = DiscreteGaussianDistributionIntegerSampler(stddev)
        LWE.__init__(self, n=n, q=q, D=D, secret_dist='noise', m=m)
示例#39
0
 def test_random_extension_fields(self, num=128):
     n = 7
     k = 3
     for i in range(num):
         p = 2
         q = randint(log(n, p).N().ceil(), 64)
         # FIXME: 2**16 has sometimes errors due to some internal infinity problem
         if q == 16: continue
         o = p**q
         s = randint(0, o - 1)
         assert s == templ_generic(n, k, o, s)
         assert s == templ_generic(n, k, o, s, 'bw', None, 1)
def bkz_runtime_k_bkz2(k, n):
    """
    Runtime estimation given ‘k‘ and assuming [CheNgu12]_ estimates are correct.
    The constants in this function were derived as follows based on Table 4 in [CheNgu12]_::
    sage: dim = [100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240,
          250]
    sage: nodes = [39.0, 44.0, 49.0, 54.0, 60.0, 66.0, 72.0, 78.0, 84.0, 96.0, 99.0, 105.0,
          111.0, 120.0, 127.0, 134.0]
    sage: times = [c + log(200,2).n() for c in nodes]
    sage: T = zip(dim, nodes)
    sage: var("a,b,c,k")
    sage: f = a*k*log(k, 2.0) + b*k + c
    sage: f = f.function(k)
    sage: f.subs(find_fit(T, f, solution_dict=True))
    k |--> 0.270188776350190*k*log(k) - 1.0192050451318417*k + 16.10253135200765
    
    .. [CheNgu12] Yuanmi Chen and Phong Q. Nguyen. BKZ 2.0: Better lattice security estimates (
        Full Version).
                  2012. http://www.di.ens.fr/~ychen/research/Full_BKZ.pdf
    """
    repeat = _sage_const_3 *log(n, _sage_const_2 ) - _sage_const_2 *log(k, _sage_const_2 ) + log(log(n, _sage_const_2 ), _sage_const_2 )
    return RR(_sage_const_0p270188776350190 *k*log(k) - _sage_const_1p0192050451318417 *k + _sage_const_16p10253135200765  + repeat)
示例#41
0
def power_spectral_density(freq):
    r"""
    Return the effective power spectral density (PSD) of the detector noise
    at a given frequency.

    INPUT:

    - ``freq`` -- frequency `f` (in `\mathrm{Hz}`)

    OUTPUT:

    - effective power spectral density `S(f)` (in `\mathrm{Hz}^{-1}`)

    EXAMPLES::

        sage: from kerrgeodesic_gw import lisa_detector
        sage: Sn = lisa_detector.power_spectral_density
        sage: Sn(1.e-1)  # tol 1.0e-13
        3.3944027493062926e-39
        sage: Sn(1.e-2)  # tol 1.0e-13
        2.738383947022306e-40
        sage: Sn(1.e-3)  # tol 1.0e-13
        3.269807574220045e-38

    """
    global _psd_spline
    if not _psd_spline:
        data = []
        file_name = os.path.join(os.path.dirname(__file__),
                                 "data/Sensitivity_LISA_SciRD1806_Alloc.dat")
        with open(file_name, "r") as data_file:
            for dline in data_file:
                f, s = dline.split('\t')
                data.append((log(RDF(f), 10), log(RDF(s), 10)))
        _psd_spline = spline(data)
    if freq < 1.e-5 or freq > 1.:
        raise ValueError("frequency {} Hz is out of range".format(freq))
    freq = RDF(freq)
    return RDF(10)**(_psd_spline(log(freq, 10)))
示例#42
0
文件: lwe.py 项目: sagemath/sage
    def __init__(self, N, delta=0.01, m=None):
        """
        Construct a Ring-LWE oracle in dimension ``n=phi(N)`` where
        the modulus ``q`` and the ``stddev`` of the noise is chosen as in
        [LP2011]_.

        INPUT:

        - ``N`` - index of cyclotomic polynomial (integer > 0, must be power of 2)
        - ``delta`` - error probability per symbol (default: 0.01)
        - ``m`` - number of allowed samples or ``None`` in which case ``3*n`` is
          used (default: ``None``)

        EXAMPLES::

            sage: from sage.crypto.lwe import RingLindnerPeikert
            sage: RingLindnerPeikert(N=16)
            RingLWE(16, 1031, Discrete Gaussian sampler for polynomials of degree < 8 with σ=2.803372 in each component, x^8 + 1, 'noise', 24)
        """
        n = euler_phi(N)
        if m is None:
            m = 3*n
        # Find c>=1 such that c*exp((1-c**2)/2))**(2*n) == 2**-40
        #  i.e c>=1 such that 2*n*log(c)+n*(1-c**2) + 40*log(2) == 0
        c = SR.var('c')
        c = find_root(2*n*log(c)+n*(1-c**2) + 40*log(2) == 0, 1, 10)
        # Upper bound on s**2/t
        s_t_bound = (sqrt(2) * pi / c / sqrt(2*n*log(2/delta))).n()
        # Interpretation of "choose q just large enough to allow for a Gaussian parameter s>=8" in [LP2011]_
        q = next_prime(floor(2**round(log(256 / s_t_bound, 2))))
        # Gaussian parameter as defined in [LP2011]_
        s = sqrt(s_t_bound*floor(q/4))
        # Transform s into stddev
        stddev = s/sqrt(2*pi.n())
        D = DiscreteGaussianDistributionPolynomialSampler(ZZ['x'], n, stddev)
        RingLWE.__init__(self, N=N, q=q, D=D, poly=None, secret_dist='noise', m=m)
示例#43
0
    def _derivative_(self, z, diff_param=None):
        r"""
        The derivative of `\operatorname{Li}(z) is `1/log(z)`.

        EXAMPLES::

            sage: x = var('x')
            sage: f = log_integral_offset(x)
            sage: f.diff(x)
            1/log(x)

            sage: f = log_integral_offset(x^2)
            sage: f.diff(x)
            2*x/log(x^2)
        """
        return 1 / log(z)
示例#44
0
    def _derivative_(self, z, diff_param=None):
        """
        The derivative of `\operatorname{Li}(z) is `1/log(z)`.

        EXAMPLES::

            sage: x = var('x')
            sage: f = log_integral_offset(x)
            sage: f.diff(x)
            1/log(x)

            sage: f = log_integral_offset(x^2)
            sage: f.diff(x)
            2*x/log(x^2)

        """
        return 1/log(z)
示例#45
0
            def _2f1(a, b, c, z):
                """
                Evaluation of 2F1(a, b; c; z), assuming a, b, c positive
                integers or half-integers
                """
                if b == c:
                    return (1 - z) ** (-a)
                if a == c:
                    return (1 - z) ** (-b)
                if a == 0 or b == 0:
                    return Integer(1)
                if a > b:
                    a, b = b, a
                if b >= 2:
                    F1 = _2f1(a, b - 1, c, z)
                    F2 = _2f1(a, b - 2, c, z)
                    q = (b - 1) * (z - 1)
                    return (((c - 2 * b + 2 + (b - a - 1) * z) * F1 +
                            (b - c - 1) * F2) / q)
                if c > 2:
                    # how to handle this case?
                    if a - c + 1 == 0 or b - c + 1 == 0:
                        raise NotImplementedError
                    F1 = _2f1(a, b, c - 1, z)
                    F2 = _2f1(a, b, c - 2, z)
                    r1 = (c - 1) * (2 - c - (a + b - 2 * c + 3) * z)
                    r2 = (c - 1) * (c - 2) * (1 - z)
                    q = (a - c + 1) * (b - c + 1) * z
                    return (r1 * F1 + r2 * F2) / q

                if (a, b, c) == (R12, 1, 2):
                    return (2 - 2 * sqrt(1 - z)) / z
                if (a, b, c) == (1, 1, 2):
                    return -log(1 - z) / z
                if (a, b, c) == (1, R32, R12):
                    return (1 + z) / (1 - z) ** 2
                if (a, b, c) == (1, R32, 2):
                    return 2 * (1 / sqrt(1 - z) - 1) / z
                if (a, b, c) == (R32, 2, R12):
                    return (1 + 3 * z) / (1 - z) ** 3
                if (a, b, c) == (R32, 2, 1):
                    return (2 + z) / (2 * (sqrt(1 - z) * (1 - z) ** 2))
                if (a, b, c) == (2, 2, 1):
                    return (1 + z) / (1 - z) ** 3
                raise NotImplementedError
示例#46
0
            def _2f1(a, b, c, z):
                """
                Evaluation of 2F1(a, b, c, z), assuming a, b, c positive
                integers or half-integers
                """
                if b == c:
                    return (1 - z)**(-a)
                if a == c:
                    return (1 - z)**(-b)
                if a == 0 or b == 0:
                    return Integer(1)
                if a > b:
                    a, b = b, a
                if b >= 2:
                    F1 = _2f1(a, b - 1, c, z)
                    F2 = _2f1(a, b - 2, c, z)
                    q = (b - 1) * (z - 1)
                    return (((c - 2 * b + 2 + (b - a - 1) * z) * F1 +
                             (b - c - 1) * F2) / q)
                if c > 2:
                    # how to handle this case?
                    if a - c + 1 == 0 or b - c + 1 == 0:
                        raise NotImplementedError
                    F1 = _2f1(a, b, c - 1, z)
                    F2 = _2f1(a, b, c - 2, z)
                    r1 = (c - 1) * (2 - c - (a + b - 2 * c + 3) * z)
                    r2 = (c - 1) * (c - 2) * (1 - z)
                    q = (a - c + 1) * (b - c + 1) * z
                    return (r1 * F1 + r2 * F2) / q

                if (a, b, c) == (R12, 1, 2):
                    return (2 - 2 * sqrt(1 - z)) / z
                if (a, b, c) == (1, 1, 2):
                    return -log(1 - z) / z
                if (a, b, c) == (1, R32, R12):
                    return (1 + z) / (1 - z)**2
                if (a, b, c) == (1, R32, 2):
                    return 2 * (1 / sqrt(1 - z) - 1) / z
                if (a, b, c) == (R32, 2, R12):
                    return (1 + 3 * z) / (1 - z)**3
                if (a, b, c) == (R32, 2, 1):
                    return (2 + z) / (2 * (sqrt(1 - z) * (1 - z)**2))
                if (a, b, c) == (2, 2, 1):
                    return (1 + z) / (1 - z)**3
                raise NotImplementedError
示例#47
0
def newton_iteration(G, n):
    r"""Returns a truncated series `y = y(x)` satisfying

    .. math::

        G(x,y(x)) \equiv 0 \bmod{x^r}

    where $r = \ceil{\log_2{n}}$. Based on the algorithm in [XXX].

    Parameters
    ----------
    G, x, y : polynomial
        A polynomial in `x` and `y`.
    n : int
        Requested degree of the series expansion.

    Notes
    -----
    This algorithm returns the series up to order :math:`2^r > n`. Any
    choice of order below :math:`2^r` will return the same series.

    """
    R = G.parent()
    x, y = R.gens()
    if n < 0:
        raise ValueError('Number of terms must be positive. (n=%d' % n)
    elif n == 0:
        return R(0)

    phi = G
    phiprime = phi.derivative(y)
    try:
        pi = R(x).polynomial(x)
        gi = R(0)
        si = R(phiprime(x, gi)).polynomial(x).inverse_mod(pi)
    except NotImplementedError:
        raise ValueError('Newton iteration for computing regular part of '
                         'Puiseux expansion failed. Curve is most likely '
                         'not regular at center.')

    r = ceil(log(n, 2))
    for i in range(r):
        gi, si, pi = newton_iteration_step(phi, phiprime, gi, si, pi)
    return R(gi)
示例#48
0
def newton_iteration(G, n):
    r"""Returns a truncated series `y = y(x)` satisfying

    .. math::

        G(x,y(x)) \equiv 0 \bmod{x^r}

    where $r = \ceil{\log_2{n}}$. Based on the algorithm in [XXX].

    Parameters
    ----------
    G, x, y : polynomial
        A polynomial in `x` and `y`.
    n : int
        Requested degree of the series expansion.

    Notes
    -----
    This algorithm returns the series up to order :math:`2^r > n`. Any
    choice of order below :math:`2^r` will return the same series.

    """
    R = G.parent()
    x,y = R.gens()
    if n < 0:
        raise ValueError('Number of terms must be positive. (n=%d'%n)
    elif n == 0:
        return R(0)

    phi = G
    phiprime = phi.derivative(y)
    try:
        pi = R(x).polynomial(x)
        gi = R(0)
        si = R(phiprime(x,gi)).polynomial(x).inverse_mod(pi)
    except NotImplementedError:
        raise ValueError('Newton iteration for computing regular part of '
                         'Puiseux expansion failed. Curve is most likely '
                         'not regular at center.')

    r = ceil(log(n,2))
    for i in range(r):
        gi,si,pi = newton_iteration_step(phi,phiprime,gi,si,pi)
    return R(gi)
示例#49
0
    def check_logarithmic_edge_equations_and_positivity(self, NumericalField):
        """
        Check that the shapes have positive imaginary part and that the
        logarithmic gluing equations have small error.

        The shapes are coerced into the field given as argument before the
        logarithm is computed. It can be, e.g., a ComplexIntervalField.
        """

        # For each edge
        for edge in self.mcomplex.Edges:

            # The complex interval arithmetic value of the logarithmic
            # version of the edge equation.
            log_sum = 0

            # Iterate through edge embeddings
            for tet, perm in edge.embeddings():

                shape = CuspCrossSectionBase._shape_for_edge_embedding(
                    tet, perm)

                numerical_shape = NumericalField(shape)

                log_shape = log(numerical_shape)

                # Note that this is true for z in R, R < 0 as well,
                # but then it would fail for 1 - 1/z or 1 / (1-z)

                if not (log_shape.imag() > 0):
                    raise ShapePositiveImaginaryPartNumericalVerifyError(
                        numerical_shape)

                # Take logarithm and accumulate
                log_sum += log_shape

            twoPiI = NumericalField.pi() * NumericalField(2j)

            if not abs(log_sum - twoPiI) < 1e-7:
                raise EdgeEquationLogLiftNumericalVerifyError(log_sum)
示例#50
0
def _N0_nodenominators(p, g, n):
    """
    Return the necessary p-adic precision for the Frobenius matrix to deduce
    the characteristic polynomial of Frobenius using the Newton identities,
    using  :meth:`charpoly_frobenius`, which assumes that the Frobenius matrix
    is integral, i.e., has no denominators.


    INPUT:

    - `p` - prime
    - `g` - genus
    - `n` - degree of residue field

    TESTS::

        sage: sage.schemes.cyclic_covers.cycliccover_finite_field._N0_nodenominators(4999, 4, 5)
        11
    """
    return max(
        ceil(log(2 * (2 * g) / ZZ(i), p) + (n * i) / ZZ(2))
        for i in range(1, g + 1))
示例#51
0
    def __init__(self, n, secret_dist='uniform', m=None):
        """
        Construct LWE instance parameterised by security paramter ``n`` where
        the modulus ``q`` and the ``stddev`` of the noise are chosen as in
        [Reg09]_.

        INPUT:

        - ``n`` - security paramter (integer > 0)
        - ``secret_dist`` - distribution of the secret. See documentation of :class:`LWE`
          for details (default='uniform')
        - ``m`` - number of allowed samples or ``None`` if no such limit exists
          (default: ``None``)

        EXAMPLES::

            sage: Regev(n=20)
            LWE(20, 401, DiscreteGaussianSamplerRejection(1.915069, 401, 4), 'uniform', None)
        """
        q = ZZ(next_prime(n**2))
        s = RR(1 / (RR(n).sqrt() * log(n, 2)**2) * q)
        D = DiscreteGaussianSampler(s / sqrt(2 * pi.n()), q)
        LWE.__init__(self, n=n, q=q, D=D, secret_dist=secret_dist, m=m)
示例#52
0
文件: lwe.py 项目: sagemath/sage
    def __init__(self, n, secret_dist='uniform', m=None):
        """
        Construct LWE instance parameterised by security parameter ``n`` where
        the modulus ``q`` and the ``stddev`` of the noise are chosen as in
        [Reg09]_.

        INPUT:

        - ``n`` - security parameter (integer > 0)
        - ``secret_dist`` - distribution of the secret. See documentation of :class:`LWE`
          for details (default='uniform')
        - ``m`` - number of allowed samples or ``None`` if no such limit exists
          (default: ``None``)

        EXAMPLES::

            sage: from sage.crypto.lwe import Regev
            sage: Regev(n=20)
            LWE(20, 401, Discrete Gaussian sampler over the Integers with sigma = 1.915069 and c = 401, 'uniform', None)
        """
        q = ZZ(next_prime(n**2))
        s = RR(1/(RR(n).sqrt() * log(n, 2)**2) * q)
        D = DiscreteGaussianDistributionIntegerSampler(s/sqrt(2*pi.n()), q)
        LWE.__init__(self, n=n, q=q, D=D, secret_dist=secret_dist, m=m)
def gghlite_latex_table(L, K, **kwds):
    """
    Generate a table with parameter estimates for ‘λ P L‘ and ‘κ P K‘.
    :param L: a list of ‘λ‘
    :param K: a list of ‘κ‘
    :returns: a string, ready to be pasted into TeX
    """
    ret = []
    for l in L:
        for k in K:
            line = []
            current = gghlite_brief(l, k, **kwds)
            line.append("%3d" % current[u"λ"])
            line.append("%3d" % current[u"κ"])
            line.append("$2^{%2d}$" % log(current["n"], _sage_const_2 ))
            t = u"$«2^{%7.1f}$" % log(current["q"], _sage_const_2 ).n()
            line.append(u"%9s" % (t,))
            t = u"$«2^{%4.1f}$" % log(current["|enc|"], _sage_const_2 ).n()
            line.append(u"%9s" % (t,))
            t = u"$«2^{%4.1f}$" % log(current["|par|"], _sage_const_2 ).n()
            line.append(u"%9s" % (t,))
            line.append("%8.6f" % current[u"δ_0"])
            t = u"$«2^{%5.1f}$" % log(current[u"bkz2"], _sage_const_2 )
            line.append(u"%9s" % (t,))
            t = u"$«2^{%5.1f}$" % log(current[u"sieve"], _sage_const_2 )
            line.append(u"%9s" % (t,))
            ret.append(u" & ".join(line) + "\\\\")
        ret.append(r"\midrule")

    header = []
    header.append(r"\begin{tabular*}{0.75\textwidth}{@{\extracolsep{\fill}} "
                  + ("r" * _sage_const_9 ) + "}")
    header.append(r"\toprule")
    line = u"$λ$ & $κ$ & $n$ & $q$ & \\encs & \\pars & $δ_0$ & BKZ Enum & BKZ Sieve\\\\"
    header.append(line)
    header.append(r"\midrule")
    ret = header + ret
    ret.append(r"\end{tabular*}")
    return "\n".join(ret)
def gghlite_latex_table(L, K, **kwds):
    """
    Generate a table with parameter estimates for ‘λ P L‘ and ‘κ P K‘.
    :param L: a list of ‘λ‘
    :param K: a list of ‘κ‘
    :returns: a string, ready to be pasted into TeX
    """
    ret = []
    for l in L:
        for k in K:
            line = []
            current = gghlite_brief(l, k, **kwds)
            line.append("%3d" % current[u"λ"])
            line.append("%3d" % current[u"κ"])
            line.append("$2^{%2d}$" % log(current["n"], _sage_const_2))
            t = u"$«2^{%7.1f}$" % log(current["q"], _sage_const_2).n()
            line.append(u"%9s" % (t, ))
            t = u"$«2^{%4.1f}$" % log(current["|enc|"], _sage_const_2).n()
            line.append(u"%9s" % (t, ))
            t = u"$«2^{%4.1f}$" % log(current["|par|"], _sage_const_2).n()
            line.append(u"%9s" % (t, ))
            line.append("%8.6f" % current[u"δ_0"])
            t = u"$«2^{%5.1f}$" % log(current[u"bkz2"], _sage_const_2)
            line.append(u"%9s" % (t, ))
            t = u"$«2^{%5.1f}$" % log(current[u"sieve"], _sage_const_2)
            line.append(u"%9s" % (t, ))
            ret.append(u" & ".join(line) + "\\\\")
        ret.append(r"\midrule")

    header = []
    header.append(r"\begin{tabular*}{0.75\textwidth}{@{\extracolsep{\fill}} " +
                  ("r" * _sage_const_9) + "}")
    header.append(r"\toprule")
    line = u"$λ$ & $κ$ & $n$ & $q$ & \\encs & \\pars & $δ_0$ & BKZ Enum & BKZ Sieve\\\\"
    header.append(line)
    header.append(r"\midrule")
    ret = header + ret
    ret.append(r"\end{tabular*}")
    return "\n".join(ret)
示例#55
0
    def _name_maker(self, names):
        r"""
        Helper function to create names of elements of algebraic structures.

        INPUT:
        Identical to the input for :class:`OperationTable` and :meth:`change_names`,
        so look there for details.

        OUTPUT:

        - ``width`` - an integer giving the maximum width of the strings
          describing the elements.  This is used for formatting the ASCII
          version of the table.
        - ``name_list`` - a list of strings naming the elements, in the
          same order as given by the :meth:`list` method.
        - ``name_dict`` - a dictionary giving the correspondence between the
          strings and the actual elements.  So the keys are the strings and
          the values are the elements of the structure.

        EXAMPLES:
        This routine is tested extensively in the :class:`OperationTable`
        and :meth:`change_names` methods.  So we just just demonstrate
        the nature of the output here. ::

            sage: from sage.matrix.operation_table import OperationTable
            sage: G=SymmetricGroup(3)
            sage: T=OperationTable(G, operator.mul)
            sage: w, l, d = T._name_maker('letters')
            sage: w
            1
            sage: l[0]
            'a'
            sage: d['a']
            ()

        TESTS:

        We test the error conditions here, rather than as part of the
        doctests for the :class:`OperationTable` and :meth:`change_names`
        methods that rely on this one. ::

            sage: from sage.matrix.operation_table import OperationTable
            sage: G=AlternatingGroup(3)
            sage: T=OperationTable(G, operator.mul)
            sage: T._name_maker(['x'])
            Traceback (most recent call last):
            ...
            ValueError: list of element names must be the same size as the set, 1 != 3
            sage: T._name_maker(['x', 'y', 4])
            Traceback (most recent call last):
            ...
            ValueError: list of element names must only contain strings, not 4
            sage: T._name_maker('blatzo')
            Traceback (most recent call last):
            ...
            ValueError: element names must be a list, or one of the keywords: 'letters', 'digits', 'elements'
        """
        from sage.functions.log import log
        name_list = []
        if names == 'digits':
            if self._n == 0 or self._n == 1:
                width = 1
            else:
                width = int(log(self._n - 1, 10)) + 1
            for i in range(self._n):
                name_list.append('{0:0{1}d}'.format(i, width))
        elif names == 'letters':
            from string import ascii_lowercase as letters
            from sage.rings.integer import Integer
            base = len(letters)
            if self._n == 0 or self._n == 1:
                width = 1
            else:
                width = int(log(self._n - 1, base)) + 1
            for i in range(self._n):
                places = Integer(i).digits(base=base,
                                           digits=letters,
                                           padto=width)
                places.reverse()
                name_list.append(''.join(places))
        elif names == 'elements':
            width = 0
            for e in self._elts:
                estr = repr(e)
                if len(estr) > width:
                    width = len(estr)
                name_list.append(estr)
        elif isinstance(names, list):
            if len(names) != self._n:
                raise ValueError(
                    'list of element names must be the same size as the set, %s != %s'
                    % (len(names), self._n))
            width = 0
            for str in names:
                if not isinstance(str, six.string_types):
                    raise ValueError(
                        'list of element names must only contain strings, not %s'
                        % str)
                if len(str) > width:
                    width = len(str)
                name_list.append(str)
        else:
            raise ValueError(
                "element names must be a list, or one of the keywords: 'letters', 'digits', 'elements'"
            )
        name_dict = {}
        for i in range(self._n):
            name_dict[name_list[i]] = self._elts[i]
        return width, name_list, name_dict
示例#56
0
    def encrypt(self, P, K, seed=None):
        r"""
        Apply the Blum-Goldwasser scheme to encrypt the plaintext ``P`` using
        the public key ``K``.

        INPUT:

        - ``P`` -- a non-empty string of plaintext. The string ``""`` is
          an empty string, whereas ``" "`` is a string consisting of one
          white space character. The plaintext can be a binary string or
          a string of ASCII characters. Where ``P`` is an ASCII string, then
          ``P`` is first encoded as a binary string prior to encryption.

        - ``K`` -- a public key, which is the product of two Blum primes.

        - ``seed`` -- (default: ``None``) if `p` and `q` are Blum primes and
          `n = pq` is a public key, then ``seed`` is a quadratic residue in
          the multiplicative group `(\ZZ/n\ZZ)^{\ast}`. If ``seed=None``,
          then the function would generate its own random quadratic residue
          in `(\ZZ/n\ZZ)^{\ast}`. Where a value for ``seed`` is provided,
          it is your responsibility to ensure that the seed is a
          quadratic residue in the multiplicative group `(\ZZ/n\ZZ)^{\ast}`.

        OUTPUT:

        - The ciphertext resulting from encrypting ``P`` using the public
          key ``K``. The ciphertext `C` is of the form
          `C = (c_1, c_2, \dots, c_t, x_{t+1})`. Each `c_i` is a
          sub-block of binary string and `x_{t+1}` is the result of the
          `t+1`-th iteration of the Blum-Blum-Shub algorithm.

        ALGORITHM:

        The Blum-Goldwasser encryption algorithm is described in Algorithm
        8.56, page 309 of [MenezesEtAl1996]_. The algorithm works as follows:

        #. Let `n` be a public key, where `n = pq` is the product of two
           distinct Blum primes `p` and `q`.
        #. Let `k = \lfloor \log_2(n) \rfloor` and
           `h = \lfloor \log_2(k) \rfloor`.
        #. Let `m = m_1 m_2 \cdots m_t` be the message (plaintext) where
           each `m_i` is a binary string of length `h`.
        #. Choose a random seed `x_0`, which is a quadratic residue in
           the multiplicative group `(\ZZ/n\ZZ)^{\ast}`. That is, choose
           a random `r \in (\ZZ/n\ZZ)^{\ast}` and compute
           `x_0 = r^2 \bmod n`.
        #. For `i` from 1 to `t`, do:

           #. Let `x_i = x_{i-1}^2 \bmod n`.
           #. Let `p_i` be the `h` least significant bits of `x_i`.
           #. Let `c_i = p_i \oplus m_i`.

        #. Compute `x_{t+1} = x_t^2 \bmod n`.
        #. The ciphertext is `c = (c_1, c_2, \dots, c_t, x_{t+1})`.

        The value `h` in the algorithm is the sub-block length. If the
        binary string representing the message cannot be divided into blocks
        of length `h` each, then other sub-block lengths would be used
        instead. The sub-block lengths to fall back on are in the
        following order: 16, 8, 4, 2, 1.

        EXAMPLES:

        The following encryption example is taken from Example 8.57,
        pages 309--310 of [MenezesEtAl1996]_. Here, we encrypt a binary
        string::

            sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
            sage: bg = BlumGoldwasser()
            sage: p = 499; q = 547; n = p * q
            sage: P = "10011100000100001100"
            sage: C = bg.encrypt(P, n, seed=159201); C
            ([[0, 0, 1, 0], [0, 0, 0, 0], [1, 1, 0, 0], [1, 1, 1, 0], [0, 1, 0, 0]], 139680)

        Convert the ciphertext sub-blocks into a binary string::

            sage: bin = BinaryStrings()
            sage: bin(flatten(C[0]))
            00100000110011100100

        Now encrypt an ASCII string. The result is random; no seed is
        provided to the encryption function so the function generates its
        own random seed::

            sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
            sage: bg = BlumGoldwasser()
            sage: K = 32300619509
            sage: P = "Blum-Goldwasser encryption"
            sage: bg.encrypt(P, K)  # random
            ([[1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0], \
            [1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1], \
            [0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0], \
            [0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1], \
            [1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0], \
            [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1], \
            [1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0], \
            [1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1], \
            [0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0], \
            [1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1], \
            [1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1], \
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0], \
            [0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1]], 3479653279)

        TESTS:

        The plaintext cannot be an empty string. ::

            sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
            sage: bg = BlumGoldwasser()
            sage: bg.encrypt("", 3)
            Traceback (most recent call last):
            ...
            ValueError: The plaintext cannot be an empty string.
        """
        # sanity check
        if P == "":
            raise ValueError("The plaintext cannot be an empty string.")
        n = K
        k = floor(log(n, base=2))
        h = floor(log(k, base=2))
        bin = BinaryStrings()
        M = ""
        try:
            # the plaintext is a binary string
            M = bin(P)
        except TypeError:
            # encode the plaintext as a binary string
            # An exception might be raised here if P cannot be encoded as a
            # binary string.
            M = bin.encoding(P)
        # the number of plaintext sub-blocks; each sub-block has length h
        t = 0
        try:
            # Attempt to use t and h values from the algorithm described
            # in [MenezesEtAl1996].
            t = len(M) / h
            # If the following raises an exception, then we can't use
            # the t and h values specified by [MenezesEtAl1996].
            mod(len(M), t)
        # fall back to using other sub-block lengths
        except TypeError:
            # sub-blocks of length h = 16
            if mod(len(M), 16) == 0:
                h = 16
                t = len(M) // h
            # sub-blocks of length h = 8
            elif mod(len(M), 8) == 0:
                h = 8
                t = len(M) // h
            # sub-blocks of length h = 4
            elif mod(len(M), 4) == 0:
                h = 4
                t = len(M) // h
            # sub-blocks of length h = 2
            elif mod(len(M), 2) == 0:
                h = 2
                t = len(M) // h
            # sub-blocks of length h = 1
            else:
                h = 1
                t = len(M) // h
        # If no seed is provided, select a random seed.
        x0 = seed
        if seed is None:
            zmod = IntegerModRing(n)  # K = n = pq
            r = zmod.random_element().lift()
            while gcd(r, n) != 1:
                r = zmod.random_element().lift()
            x0 = power_mod(r, 2, n)
        # perform the encryption
        to_int = lambda x: int(str(x))
        C = []
        for i in xrange(t):
            x1 = power_mod(x0, 2, n)
            p = least_significant_bits(x1, h)
            # xor p with a sub-block of length h. There are t sub-blocks of
            # length h each.
            C.append(
                list(map(xor, p, [to_int(_) for _ in M[i * h:(i + 1) * h]])))
            x0 = x1
        x1 = power_mod(x0, 2, n)
        return (C, x1)
示例#57
0
文件: tides.py 项目: Findstat/sage
def subexpressions_list(f, pars=None):
    """
    Construct the lists with the intermediate steps on the evaluation of the
    function.

    INPUT:

    - ``f`` -- a symbolic function of several components.

    - ``pars`` -- a list of the parameters that appear in the function
      this should be the symbolic constants that appear in f but are not
      arguments.

    OUTPUT:

    - a list of the intermediate subexpressions that appear in the evaluation
      of f.

    - a list with the operations used to construct each of the subexpressions.
      each element of this list is a tuple, formed by a string describing the
      operation made, and the operands.

    For the trigonometric functions, some extra expressions will be added.
    These extra expressions will be used later to compute their derivatives.


    EXAMPLES::

        sage: from sage.interfaces.tides import subexpressions_list
        sage: var('x,y')
        (x, y)
        sage: f(x,y) = [x^2+y, cos(x)/log(y)]
        sage: subexpressions_list(f)
        ([x^2, x^2 + y, sin(x), cos(x), log(y), cos(x)/log(y)],
        [('mul', x, x),
        ('add', y, x^2),
        ('sin', x),
        ('cos', x),
        ('log', y),
        ('div', log(y), cos(x))])

    ::

        sage: f(a)=[cos(a), arctan(a)]
        sage: from sage.interfaces.tides import subexpressions_list
        sage: subexpressions_list(f)
        ([sin(a), cos(a), a^2, a^2 + 1, arctan(a)],
        [('sin', a), ('cos', a), ('mul', a, a), ('add', 1, a^2), ('atan', a)])

    ::

        sage: from sage.interfaces.tides import subexpressions_list
        sage: var('s,b,r')
        (s, b, r)
        sage: f(t,x,y,z)= [s*(y-x),x*(r-z)-y,x*y-b*z]
        sage: subexpressions_list(f,[s,b,r])
        ([-y,
        x - y,
        s*(x - y),
        -s*(x - y),
        -z,
        r - z,
        (r - z)*x,
        -y,
        (r - z)*x - y,
        x*y,
        b*z,
        -b*z,
        x*y - b*z],
        [('mul', -1, y),
        ('add', -y, x),
        ('mul', x - y, s),
        ('mul', -1, s*(x - y)),
        ('mul', -1, z),
        ('add', -z, r),
        ('mul', x, r - z),
        ('mul', -1, y),
        ('add', -y, (r - z)*x),
        ('mul', y, x),
        ('mul', z, b),
        ('mul', -1, b*z),
        ('add', -b*z, x*y)])

    ::

        sage: var('x, y')
        (x, y)
        sage: f(x,y)=[exp(x^2+sin(y))]
        sage: from sage.interfaces.tides import *
        sage: subexpressions_list(f)
        ([x^2, sin(y), cos(y), x^2 + sin(y), e^(x^2 + sin(y))],
        [('mul', x, x),
        ('sin', y),
        ('cos', y),
        ('add', sin(y), x^2),
        ('exp', x^2 + sin(y))])


    """
    from sage.functions.trig import sin, cos, arcsin, arctan, arccos
    variables = f[0].arguments()
    if not pars:
        parameters = []
    else:
        parameters = pars
    varpar = list(parameters) + list(variables)
    F = symbolic_expression([i(*variables) for i in f]).function(*varpar)
    lis = flatten([fast_callable(i,vars=varpar).op_list() for i in F], max_level=1)
    stack = []
    const =[]
    stackcomp=[]
    detail=[]
    for i in lis:
        if i[0] == 'load_arg':
            stack.append(varpar[i[1]])
        elif i[0] == 'ipow':
            if i[1] in NN:
                basis = stack[-1]
                for j in range(i[1]-1):
                    a=stack.pop(-1)
                    detail.append(('mul', a, basis))
                    stack.append(a*basis)
                    stackcomp.append(stack[-1])
            else:
                detail.append(('pow',stack[-1],i[1]))
                stack[-1]=stack[-1]**i[1]
                stackcomp.append(stack[-1])

        elif i[0] == 'load_const':
            const.append(i[1])
            stack.append(i[1])
        elif i == 'mul':
            a=stack.pop(-1)
            b=stack.pop(-1)
            detail.append(('mul', a, b))
            stack.append(a*b)
            stackcomp.append(stack[-1])

        elif i == 'div':
            a=stack.pop(-1)
            b=stack.pop(-1)
            detail.append(('div', a, b))
            stack.append(b/a)
            stackcomp.append(stack[-1])

        elif i == 'add':
            a=stack.pop(-1)
            b=stack.pop(-1)
            detail.append(('add',a,b))
            stack.append(a+b)
            stackcomp.append(stack[-1])

        elif i == 'pow':
            a=stack.pop(-1)
            b=stack.pop(-1)
            detail.append(('pow', b, a))
            stack.append(b**a)
            stackcomp.append(stack[-1])

        elif i[0] == 'py_call' and str(i[1])=='log':
            a=stack.pop(-1)
            detail.append(('log', a))
            stack.append(log(a))
            stackcomp.append(stack[-1])

        elif i[0] == 'py_call' and str(i[1])=='exp':
            a=stack.pop(-1)
            detail.append(('exp', a))
            stack.append(exp(a))
            stackcomp.append(stack[-1])

        elif i[0] == 'py_call' and str(i[1])=='sin':
            a=stack.pop(-1)
            detail.append(('sin', a))
            detail.append(('cos', a))
            stackcomp.append(sin(a))
            stackcomp.append(cos(a))
            stack.append(sin(a))

        elif i[0] == 'py_call' and str(i[1])=='cos':
            a=stack.pop(-1)
            detail.append(('sin', a))
            detail.append(('cos', a))
            stackcomp.append(sin(a))
            stackcomp.append(cos(a))
            stack.append(cos(a))

        elif i[0] == 'py_call' and str(i[1])=='tan':
            a=stack.pop(-1)
            b = sin(a)
            c = cos(a)
            detail.append(('sin', a))
            detail.append(('cos', a))
            detail.append(('div', b, c))
            stackcomp.append(b)
            stackcomp.append(c)
            stackcomp.append(b/c)
            stack.append(b/c)

        elif i[0] == 'py_call' and str(i[1])=='arctan':
            a=stack.pop(-1)
            detail.append(('mul', a, a))
            detail.append(('add', 1, a*a))
            detail.append(('atan', a))
            stackcomp.append(a*a)
            stackcomp.append(1+a*a)
            stackcomp.append(arctan(a))
            stack.append(arctan(a))

        elif i[0] == 'py_call' and str(i[1])=='arcsin':
            a=stack.pop(-1)
            detail.append(('mul', a, a))
            detail.append(('mul', -1, a*a))
            detail.append(('add', 1, -a*a))
            detail.append(('pow', 1- a*a, 0.5))
            detail.append(('asin', a))
            stackcomp.append(a*a)
            stackcomp.append(-a*a)
            stackcomp.append(1-a*a)
            stackcomp.append(sqrt(1-a*a))
            stackcomp.append(arcsin(a))
            stack.append(arcsin(a))

        elif i[0] == 'py_call' and str(i[1])=='arccos':
            a=stack.pop(-1)
            detail.append(('mul', a, a))
            detail.append(('mul', -1, a*a))
            detail.append(('add', 1, -a*a))
            detail.append(('pow', 1- a*a, 0.5))
            detail.append(('mul', -1, sqrt(1-a*a)))
            detail.append(('acos', a))
            stackcomp.append(a*a)
            stackcomp.append(-a*a)
            stackcomp.append(1-a*a)
            stackcomp.append(sqrt(1-a*a))
            stackcomp.append(-sqrt(1-a*a))
            stackcomp.append(arccos(a))
            stack.append(arccos(a))

        elif i[0] == 'py_call' and 'sqrt' in str(i[1]):
            a=stack.pop(-1)
            detail.append(('pow', a, 0.5))
            stackcomp.append(sqrt(a))
            stack.append(sqrt(a))


        elif i == 'neg':
            a = stack.pop(-1)
            detail.append(('mul', -1, a))
            stack.append(-a)
            stackcomp.append(-a)

    return stackcomp,detail
示例#58
0
    def encrypt(self, P, K, seed=None):
        r"""
        Apply the Blum-Goldwasser scheme to encrypt the plaintext ``P`` using
        the public key ``K``.

        INPUT:

        - ``P`` -- a non-empty string of plaintext. The string ``""`` is
          an empty string, whereas ``" "`` is a string consisting of one
          white space character. The plaintext can be a binary string or
          a string of ASCII characters. Where ``P`` is an ASCII string, then
          ``P`` is first encoded as a binary string prior to encryption.

        - ``K`` -- a public key, which is the product of two Blum primes.

        - ``seed`` -- (default: ``None``) if `p` and `q` are Blum primes and
          `n = pq` is a public key, then ``seed`` is a quadratic residue in
          the multiplicative group `(\ZZ/n\ZZ)^{\ast}`. If ``seed=None``,
          then the function would generate its own random quadratic residue
          in `(\ZZ/n\ZZ)^{\ast}`. Where a value for ``seed`` is provided,
          it is your responsibility to ensure that the seed is a
          quadratic residue in the multiplicative group `(\ZZ/n\ZZ)^{\ast}`.

        OUTPUT:

        - The ciphertext resulting from encrypting ``P`` using the public
          key ``K``. The ciphertext `C` is of the form
          `C = (c_1, c_2, \dots, c_t, x_{t+1})`. Each `c_i` is a
          sub-block of binary string and `x_{t+1}` is the result of the
          `t+1`-th iteration of the Blum-Blum-Shub algorithm.

        ALGORITHM:

        The Blum-Goldwasser encryption algorithm is described in Algorithm
        8.56, page 309 of [MvOV1996]_. The algorithm works as follows:

        #. Let `n` be a public key, where `n = pq` is the product of two
           distinct Blum primes `p` and `q`.
        #. Let `k = \lfloor \log_2(n) \rfloor` and
           `h = \lfloor \log_2(k) \rfloor`.
        #. Let `m = m_1 m_2 \cdots m_t` be the message (plaintext) where
           each `m_i` is a binary string of length `h`.
        #. Choose a random seed `x_0`, which is a quadratic residue in
           the multiplicative group `(\ZZ/n\ZZ)^{\ast}`. That is, choose
           a random `r \in (\ZZ/n\ZZ)^{\ast}` and compute
           `x_0 = r^2 \bmod n`.
        #. For `i` from 1 to `t`, do:

           #. Let `x_i = x_{i-1}^2 \bmod n`.
           #. Let `p_i` be the `h` least significant bits of `x_i`.
           #. Let `c_i = p_i \oplus m_i`.

        #. Compute `x_{t+1} = x_t^2 \bmod n`.
        #. The ciphertext is `c = (c_1, c_2, \dots, c_t, x_{t+1})`.

        The value `h` in the algorithm is the sub-block length. If the
        binary string representing the message cannot be divided into blocks
        of length `h` each, then other sub-block lengths would be used
        instead. The sub-block lengths to fall back on are in the
        following order: 16, 8, 4, 2, 1.

        EXAMPLES:

        The following encryption example is taken from Example 8.57,
        pages 309--310 of [MvOV1996]_. Here, we encrypt a binary
        string::

            sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
            sage: bg = BlumGoldwasser()
            sage: p = 499; q = 547; n = p * q
            sage: P = "10011100000100001100"
            sage: C = bg.encrypt(P, n, seed=159201); C
            ([[0, 0, 1, 0], [0, 0, 0, 0], [1, 1, 0, 0], [1, 1, 1, 0], [0, 1, 0, 0]], 139680)

        Convert the ciphertext sub-blocks into a binary string::

            sage: bin = BinaryStrings()
            sage: bin(flatten(C[0]))
            00100000110011100100

        Now encrypt an ASCII string. The result is random; no seed is
        provided to the encryption function so the function generates its
        own random seed::

            sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
            sage: bg = BlumGoldwasser()
            sage: K = 32300619509
            sage: P = "Blum-Goldwasser encryption"
            sage: bg.encrypt(P, K)  # random
            ([[1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0], \
            [1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1], \
            [0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0], \
            [0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1], \
            [1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0], \
            [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1], \
            [1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0], \
            [1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1], \
            [0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0], \
            [1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1], \
            [1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1], \
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0], \
            [0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1]], 3479653279)

        TESTS:

        The plaintext cannot be an empty string. ::

            sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
            sage: bg = BlumGoldwasser()
            sage: bg.encrypt("", 3)
            Traceback (most recent call last):
            ...
            ValueError: The plaintext cannot be an empty string.
        """
        # sanity check
        if P == "":
            raise ValueError("The plaintext cannot be an empty string.")
        n = K
        k = floor(log(n, base=2))
        h = floor(log(k, base=2))
        bin = BinaryStrings()
        M = ""
        try:
            # the plaintext is a binary string
            M = bin(P)
        except TypeError:
            # encode the plaintext as a binary string
            # An exception might be raised here if P cannot be encoded as a
            # binary string.
            M = bin.encoding(P)
        # the number of plaintext sub-blocks; each sub-block has length h
        t = 0
        try:
            # Attempt to use t and h values from the algorithm described
            # in [MvOV1996].
            t = len(M) / h
            # If the following raises an exception, then we can't use
            # the t and h values specified by [MvOV1996].
            mod(len(M), t)
        # fall back to using other sub-block lengths
        except TypeError:
            # sub-blocks of length h = 16
            if mod(len(M), 16) == 0:
                h = 16
                t = len(M) // h
            # sub-blocks of length h = 8
            elif mod(len(M), 8) == 0:
                h = 8
                t = len(M) // h
            # sub-blocks of length h = 4
            elif mod(len(M), 4) == 0:
                h = 4
                t = len(M) // h
            # sub-blocks of length h = 2
            elif mod(len(M), 2) == 0:
                h = 2
                t = len(M) // h
            # sub-blocks of length h = 1
            else:
                h = 1
                t = len(M) // h
        # If no seed is provided, select a random seed.
        x0 = seed
        if seed is None:
            zmod = IntegerModRing(n)  # K = n = pq
            r = zmod.random_element().lift()
            while gcd(r, n) != 1:
                r = zmod.random_element().lift()
            x0 = power_mod(r, 2, n)
        # perform the encryption
        to_int = lambda x: int(str(x))
        C = []
        for i in range(t):
            x1 = power_mod(x0, 2, n)
            p = least_significant_bits(x1, h)
            # xor p with a sub-block of length h. There are t sub-blocks of
            # length h each.
            C.append(list(map(xor, p, [to_int(_) for _ in M[i*h : (i+1)*h]])))
            x0 = x1
        x1 = power_mod(x0, 2, n)
        return (C, x1)