Statistiques
| Révision :

root / pobysoPythonSage / src / sageSLZ / sageSLZ.sage @ 284

Historique | Voir | Annoter | Télécharger (130,06 ko)

1 115 storres
r"""
2 115 storres
Sage core functions needed for the implementation of SLZ.
3 90 storres
4 115 storres
AUTHORS:
5 115 storres
- S.T. (2013-08): initial version
6 90 storres
7 115 storres
Examples:
8 119 storres
9 119 storres
TODO::
10 90 storres
"""
11 246 storres
sys.stderr.write("sageSLZ loading...\n")
12 115 storres
#
13 225 storres
import inspect
14 225 storres
#
15 165 storres
def slz_compute_binade(number):
16 165 storres
    """"
17 165 storres
    For a given number, compute the "binade" that is integer m such that
18 165 storres
    2^m <= number < 2^(m+1). If number == 0 return None.
19 165 storres
    """
20 165 storres
    # Checking the parameter.
21 172 storres
    # The exception construction is used to detect if number is a RealNumber
22 165 storres
    # since not all numbers have
23 165 storres
    # the mro() method. sage.rings.real_mpfr.RealNumber do.
24 165 storres
    try:
25 165 storres
        classTree = [number.__class__] + number.mro()
26 172 storres
        # If the number is not a RealNumber (or offspring thereof) try
27 165 storres
        # to transform it.
28 165 storres
        if not sage.rings.real_mpfr.RealNumber in classTree:
29 165 storres
            numberAsRR = RR(number)
30 165 storres
        else:
31 165 storres
            numberAsRR = number
32 165 storres
    except AttributeError:
33 165 storres
        return None
34 165 storres
    # Zero special case.
35 165 storres
    if numberAsRR == 0:
36 165 storres
        return RR(-infinity)
37 165 storres
    else:
38 176 storres
        realField           = numberAsRR.parent()
39 176 storres
        numberLog2          = numberAsRR.abs().log2()
40 176 storres
        floorNumberLog2     = floor(numberLog2)
41 176 storres
        ## Do not get caught by rounding of log2() both ways.
42 176 storres
        ## When numberLog2 is an integer, compare numberAsRR
43 176 storres
        #  with 2^numberLog2.
44 176 storres
        if floorNumberLog2 == numberLog2:
45 176 storres
            if numberAsRR.abs() < realField(2^floorNumberLog2):
46 176 storres
                return floorNumberLog2 - 1
47 176 storres
            else:
48 176 storres
                return floorNumberLog2
49 176 storres
        else:
50 176 storres
            return floorNumberLog2
51 165 storres
# End slz_compute_binade
52 165 storres
53 115 storres
#
54 121 storres
def slz_compute_binade_bounds(number, emin, emax=sys.maxint):
55 119 storres
    """
56 119 storres
    For given "real number", compute the bounds of the binade it belongs to.
57 121 storres
58 121 storres
    NOTE::
59 121 storres
        When number >= 2^(emax+1), we return the "fake" binade
60 121 storres
        [2^(emax+1), +infinity]. Ditto for number <= -2^(emax+1)
61 125 storres
        with interval [-infinity, -2^(emax+1)]. We want to distinguish
62 125 storres
        this case from that of "really" invalid arguments.
63 121 storres
64 119 storres
    """
65 121 storres
    # Check the parameters.
66 125 storres
    # RealNumbers or RealNumber offspring only.
67 165 storres
    # The exception construction is necessary since not all objects have
68 125 storres
    # the mro() method. sage.rings.real_mpfr.RealNumber do.
69 124 storres
    try:
70 124 storres
        classTree = [number.__class__] + number.mro()
71 124 storres
        if not sage.rings.real_mpfr.RealNumber in classTree:
72 124 storres
            return None
73 124 storres
    except AttributeError:
74 121 storres
        return None
75 121 storres
    # Non zero negative integers only for emin.
76 121 storres
    if emin >= 0 or int(emin) != emin:
77 121 storres
        return None
78 121 storres
    # Non zero positive integers only for emax.
79 121 storres
    if emax <= 0 or int(emax) != emax:
80 121 storres
        return None
81 121 storres
    precision = number.precision()
82 121 storres
    RF  = RealField(precision)
83 125 storres
    if number == 0:
84 125 storres
        return (RF(0),RF(2^(emin)) - RF(2^(emin-precision)))
85 121 storres
    # A more precise RealField is needed to avoid unwanted rounding effects
86 121 storres
    # when computing number.log2().
87 121 storres
    RRF = RealField(max(2048, 2 * precision))
88 121 storres
    # number = 0 special case, the binade bounds are
89 121 storres
    # [0, 2^emin - 2^(emin-precision)]
90 121 storres
    # Begin general case
91 119 storres
    l2 = RRF(number).abs().log2()
92 121 storres
    # Another special one: beyond largest representable -> "Fake" binade.
93 121 storres
    if l2 >= emax + 1:
94 121 storres
        if number > 0:
95 125 storres
            return (RF(2^(emax+1)), RF(+infinity) )
96 121 storres
        else:
97 121 storres
            return (RF(-infinity), -RF(2^(emax+1)))
98 165 storres
    # Regular case cont'd.
99 119 storres
    offset = int(l2)
100 121 storres
    # number.abs() >= 1.
101 119 storres
    if l2 >= 0:
102 119 storres
        if number >= 0:
103 119 storres
            lb = RF(2^offset)
104 119 storres
            ub = RF(2^(offset + 1) - 2^(-precision+offset+1))
105 119 storres
        else: #number < 0
106 119 storres
            lb = -RF(2^(offset + 1) - 2^(-precision+offset+1))
107 119 storres
            ub = -RF(2^offset)
108 121 storres
    else: # log2 < 0, number.abs() < 1.
109 119 storres
        if l2 < emin: # Denormal
110 121 storres
           # print "Denormal:", l2
111 119 storres
            if number >= 0:
112 119 storres
                lb = RF(0)
113 119 storres
                ub = RF(2^(emin)) - RF(2^(emin-precision))
114 119 storres
            else: # number <= 0
115 119 storres
                lb = - RF(2^(emin)) + RF(2^(emin-precision))
116 119 storres
                ub = RF(0)
117 119 storres
        elif l2 > emin: # Normal number other than +/-2^emin.
118 119 storres
            if number >= 0:
119 121 storres
                if int(l2) == l2:
120 121 storres
                    lb = RF(2^(offset))
121 121 storres
                    ub = RF(2^(offset+1)) - RF(2^(-precision+offset+1))
122 121 storres
                else:
123 121 storres
                    lb = RF(2^(offset-1))
124 121 storres
                    ub = RF(2^(offset)) - RF(2^(-precision+offset))
125 119 storres
            else: # number < 0
126 121 storres
                if int(l2) == l2: # Binade limit.
127 121 storres
                    lb = -RF(2^(offset+1) - 2^(-precision+offset+1))
128 121 storres
                    ub = -RF(2^(offset))
129 121 storres
                else:
130 121 storres
                    lb = -RF(2^(offset) - 2^(-precision+offset))
131 121 storres
                    ub = -RF(2^(offset-1))
132 121 storres
        else: # l2== emin, number == +/-2^emin
133 119 storres
            if number >= 0:
134 119 storres
                lb = RF(2^(offset))
135 119 storres
                ub = RF(2^(offset+1)) - RF(2^(-precision+offset+1))
136 119 storres
            else: # number < 0
137 119 storres
                lb = -RF(2^(offset+1) - 2^(-precision+offset+1))
138 119 storres
                ub = -RF(2^(offset))
139 119 storres
    return (lb, ub)
140 119 storres
# End slz_compute_binade_bounds
141 119 storres
#
142 123 storres
def slz_compute_coppersmith_reduced_polynomials(inputPolynomial,
143 123 storres
                                                 alpha,
144 123 storres
                                                 N,
145 123 storres
                                                 iBound,
146 223 storres
                                                 tBound,
147 223 storres
                                                 debug = False):
148 123 storres
    """
149 123 storres
    For a given set of arguments (see below), compute a list
150 123 storres
    of "reduced polynomials" that could be used to compute roots
151 123 storres
    of the inputPolynomial.
152 124 storres
    INPUT:
153 124 storres
154 124 storres
    - "inputPolynomial" -- (no default) a bivariate integer polynomial;
155 124 storres
    - "alpha" -- the alpha parameter of the Coppersmith algorithm;
156 124 storres
    - "N" -- the modulus;
157 124 storres
    - "iBound" -- the bound on the first variable;
158 124 storres
    - "tBound" -- the bound on the second variable.
159 124 storres
160 124 storres
    OUTPUT:
161 124 storres
162 124 storres
    A list of bivariate integer polynomial obtained using the Coppersmith
163 124 storres
    algorithm. The polynomials correspond to the rows of the LLL-reduce
164 124 storres
    reduced base that comply with the Coppersmith condition.
165 123 storres
    """
166 123 storres
    # Arguments check.
167 123 storres
    if iBound == 0 or tBound == 0:
168 179 storres
        return None
169 123 storres
    # End arguments check.
170 123 storres
    nAtAlpha = N^alpha
171 123 storres
    ## Building polynomials for matrix.
172 123 storres
    polyRing   = inputPolynomial.parent()
173 123 storres
    # Whatever the 2 variables are actually called, we call them
174 123 storres
    # 'i' and 't' in all the variable names.
175 123 storres
    (iVariable, tVariable) = inputPolynomial.variables()[:2]
176 123 storres
    #print polyVars[0], type(polyVars[0])
177 123 storres
    initialPolynomial = inputPolynomial.subs({iVariable:iVariable * iBound,
178 123 storres
                                              tVariable:tVariable * tBound})
179 223 storres
    if debug:
180 223 storres
        polynomialsList = \
181 223 storres
            spo_polynomial_to_polynomials_list_8(initialPolynomial,
182 223 storres
                                                 alpha,
183 223 storres
                                                 N,
184 223 storres
                                                 iBound,
185 223 storres
                                                 tBound,
186 223 storres
                                                 20)
187 223 storres
    else:
188 223 storres
        polynomialsList = \
189 223 storres
            spo_polynomial_to_polynomials_list_8(initialPolynomial,
190 223 storres
                                                 alpha,
191 223 storres
                                                 N,
192 223 storres
                                                 iBound,
193 223 storres
                                                 tBound,
194 223 storres
                                                 0)
195 123 storres
    #print "Polynomials list:", polynomialsList
196 123 storres
    ## Building the proto matrix.
197 123 storres
    knownMonomials = []
198 123 storres
    protoMatrix    = []
199 223 storres
    if debug:
200 223 storres
        for poly in polynomialsList:
201 223 storres
            spo_add_polynomial_coeffs_to_matrix_row(poly,
202 223 storres
                                                    knownMonomials,
203 223 storres
                                                    protoMatrix,
204 223 storres
                                                    20)
205 223 storres
    else:
206 223 storres
        for poly in polynomialsList:
207 223 storres
            spo_add_polynomial_coeffs_to_matrix_row(poly,
208 223 storres
                                                    knownMonomials,
209 223 storres
                                                    protoMatrix,
210 223 storres
                                                    0)
211 123 storres
    matrixToReduce = spo_proto_to_row_matrix(protoMatrix)
212 123 storres
    #print matrixToReduce
213 123 storres
    ## Reduction and checking.
214 163 storres
    ## S.T. changed 'fp' to None as of Sage 6.6 complying to
215 163 storres
    #  error message issued when previous code was used.
216 163 storres
    #reducedMatrix = matrixToReduce.LLL(fp='fp')
217 163 storres
    reducedMatrix = matrixToReduce.LLL(fp=None)
218 123 storres
    isLLLReduced  = reducedMatrix.is_LLL_reduced()
219 123 storres
    if not isLLLReduced:
220 179 storres
        return None
221 123 storres
    monomialsCount     = len(knownMonomials)
222 123 storres
    monomialsCountSqrt = sqrt(monomialsCount)
223 123 storres
    #print "Monomials count:", monomialsCount, monomialsCountSqrt.n()
224 123 storres
    #print reducedMatrix
225 123 storres
    ## Check the Coppersmith condition for each row and build the reduced
226 123 storres
    #  polynomials.
227 123 storres
    ccReducedPolynomialsList = []
228 123 storres
    for row in reducedMatrix.rows():
229 123 storres
        l2Norm = row.norm(2)
230 123 storres
        if (l2Norm * monomialsCountSqrt) < nAtAlpha:
231 123 storres
            #print (l2Norm * monomialsCountSqrt).n()
232 125 storres
            #print l2Norm.n()
233 123 storres
            ccReducedPolynomial = \
234 123 storres
                slz_compute_reduced_polynomial(row,
235 123 storres
                                               knownMonomials,
236 123 storres
                                               iVariable,
237 123 storres
                                               iBound,
238 123 storres
                                               tVariable,
239 123 storres
                                               tBound)
240 123 storres
            if not ccReducedPolynomial is None:
241 123 storres
                ccReducedPolynomialsList.append(ccReducedPolynomial)
242 123 storres
        else:
243 125 storres
            #print l2Norm.n() , ">", nAtAlpha
244 123 storres
            pass
245 123 storres
    if len(ccReducedPolynomialsList) < 2:
246 125 storres
        print "Less than 2 Coppersmith condition compliant vectors."
247 123 storres
        return ()
248 125 storres
    #print ccReducedPolynomialsList
249 123 storres
    return ccReducedPolynomialsList
250 123 storres
# End slz_compute_coppersmith_reduced_polynomials
251 243 storres
#
252 243 storres
def slz_compute_coppersmith_reduced_polynomials_gram(inputPolynomial,
253 243 storres
                                                     alpha,
254 243 storres
                                                     N,
255 243 storres
                                                     iBound,
256 243 storres
                                                     tBound,
257 243 storres
                                                     debug = False):
258 243 storres
    """
259 243 storres
    For a given set of arguments (see below), compute a list
260 243 storres
    of "reduced polynomials" that could be used to compute roots
261 243 storres
    of the inputPolynomial.
262 243 storres
    INPUT:
263 243 storres
264 243 storres
    - "inputPolynomial" -- (no default) a bivariate integer polynomial;
265 243 storres
    - "alpha" -- the alpha parameter of the Coppersmith algorithm;
266 243 storres
    - "N" -- the modulus;
267 243 storres
    - "iBound" -- the bound on the first variable;
268 243 storres
    - "tBound" -- the bound on the second variable.
269 243 storres
270 243 storres
    OUTPUT:
271 243 storres
272 243 storres
    A list of bivariate integer polynomial obtained using the Coppersmith
273 243 storres
    algorithm. The polynomials correspond to the rows of the LLL-reduce
274 243 storres
    reduced base that comply with the Coppersmith condition.
275 243 storres
    """
276 243 storres
    # Arguments check.
277 243 storres
    if iBound == 0 or tBound == 0:
278 243 storres
        return None
279 243 storres
    # End arguments check.
280 243 storres
    nAtAlpha = N^alpha
281 243 storres
    ## Building polynomials for matrix.
282 243 storres
    polyRing   = inputPolynomial.parent()
283 243 storres
    # Whatever the 2 variables are actually called, we call them
284 243 storres
    # 'i' and 't' in all the variable names.
285 243 storres
    (iVariable, tVariable) = inputPolynomial.variables()[:2]
286 243 storres
    #print polyVars[0], type(polyVars[0])
287 243 storres
    initialPolynomial = inputPolynomial.subs({iVariable:iVariable * iBound,
288 243 storres
                                              tVariable:tVariable * tBound})
289 243 storres
    if debug:
290 243 storres
        polynomialsList = \
291 243 storres
            spo_polynomial_to_polynomials_list_8(initialPolynomial,
292 243 storres
                                                 alpha,
293 243 storres
                                                 N,
294 243 storres
                                                 iBound,
295 243 storres
                                                 tBound,
296 243 storres
                                                 20)
297 243 storres
    else:
298 243 storres
        polynomialsList = \
299 243 storres
            spo_polynomial_to_polynomials_list_8(initialPolynomial,
300 243 storres
                                                 alpha,
301 243 storres
                                                 N,
302 243 storres
                                                 iBound,
303 243 storres
                                                 tBound,
304 243 storres
                                                 0)
305 243 storres
    #print "Polynomials list:", polynomialsList
306 243 storres
    ## Building the proto matrix.
307 243 storres
    knownMonomials = []
308 243 storres
    protoMatrix    = []
309 243 storres
    if debug:
310 243 storres
        for poly in polynomialsList:
311 243 storres
            spo_add_polynomial_coeffs_to_matrix_row(poly,
312 243 storres
                                                    knownMonomials,
313 243 storres
                                                    protoMatrix,
314 243 storres
                                                    20)
315 243 storres
    else:
316 243 storres
        for poly in polynomialsList:
317 243 storres
            spo_add_polynomial_coeffs_to_matrix_row(poly,
318 243 storres
                                                    knownMonomials,
319 243 storres
                                                    protoMatrix,
320 243 storres
                                                    0)
321 243 storres
    matrixToReduce = spo_proto_to_row_matrix(protoMatrix)
322 243 storres
    #print matrixToReduce
323 243 storres
    ## Reduction and checking.
324 243 storres
    ### In this variant we use the Pari LLL_gram reduction function.
325 243 storres
    #   It works with the Gram matrix instead of the plain matrix.
326 243 storres
    matrixToReduceTransposed = matrixToReduce.transpose()
327 243 storres
    matrixToReduceGram = matrixToReduce * matrixToReduceTransposed
328 243 storres
    ### LLL_gram returns a unimodular transformation matrix such that:
329 243 storres
    #   umt.transpose() * matrixToReduce * umt is reduced..
330 243 storres
    umt = matrixToReduceGram.LLL_gram()
331 243 storres
    #print "Unimodular transformation matrix:"
332 243 storres
    #for row in umt.rows():
333 243 storres
    #    print row
334 243 storres
    ### The computed transformation matrix is transposed and applied to the
335 243 storres
    #   left side of matrixToReduce.
336 243 storres
    reducedMatrix = umt.transpose() * matrixToReduce
337 243 storres
    #print "Reduced matrix:"
338 243 storres
    #for row in reducedMatrix.rows():
339 243 storres
    #    print row
340 243 storres
    isLLLReduced  = reducedMatrix.is_LLL_reduced()
341 243 storres
    #if not isLLLReduced:
342 243 storres
    #    return None
343 243 storres
    monomialsCount     = len(knownMonomials)
344 243 storres
    monomialsCountSqrt = sqrt(monomialsCount)
345 243 storres
    #print "Monomials count:", monomialsCount, monomialsCountSqrt.n()
346 243 storres
    #print reducedMatrix
347 243 storres
    ## Check the Coppersmith condition for each row and build the reduced
348 243 storres
    #  polynomials.
349 243 storres
    ccReducedPolynomialsList = []
350 243 storres
    for row in reducedMatrix.rows():
351 243 storres
        l2Norm = row.norm(2)
352 243 storres
        if (l2Norm * monomialsCountSqrt) < nAtAlpha:
353 243 storres
            #print (l2Norm * monomialsCountSqrt).n()
354 243 storres
            #print l2Norm.n()
355 243 storres
            ccReducedPolynomial = \
356 243 storres
                slz_compute_reduced_polynomial(row,
357 243 storres
                                               knownMonomials,
358 243 storres
                                               iVariable,
359 243 storres
                                               iBound,
360 243 storres
                                               tVariable,
361 243 storres
                                               tBound)
362 243 storres
            if not ccReducedPolynomial is None:
363 243 storres
                ccReducedPolynomialsList.append(ccReducedPolynomial)
364 243 storres
        else:
365 243 storres
            #print l2Norm.n() , ">", nAtAlpha
366 243 storres
            pass
367 243 storres
    if len(ccReducedPolynomialsList) < 2:
368 243 storres
        print "Less than 2 Coppersmith condition compliant vectors."
369 243 storres
        return ()
370 243 storres
    #print ccReducedPolynomialsList
371 243 storres
    return ccReducedPolynomialsList
372 243 storres
# End slz_compute_coppersmith_reduced_polynomials_gram
373 243 storres
#
374 247 storres
def slz_compute_coppersmith_reduced_polynomials_proj(inputPolynomial,
375 247 storres
                                                     alpha,
376 247 storres
                                                     N,
377 247 storres
                                                     iBound,
378 247 storres
                                                     tBound,
379 247 storres
                                                     debug = False):
380 247 storres
    """
381 247 storres
    For a given set of arguments (see below), compute a list
382 247 storres
    of "reduced polynomials" that could be used to compute roots
383 247 storres
    of the inputPolynomial.
384 247 storres
    INPUT:
385 247 storres
386 247 storres
    - "inputPolynomial" -- (no default) a bivariate integer polynomial;
387 247 storres
    - "alpha" -- the alpha parameter of the Coppersmith algorithm;
388 247 storres
    - "N" -- the modulus;
389 247 storres
    - "iBound" -- the bound on the first variable;
390 247 storres
    - "tBound" -- the bound on the second variable.
391 247 storres
392 247 storres
    OUTPUT:
393 247 storres
394 247 storres
    A list of bivariate integer polynomial obtained using the Coppersmith
395 247 storres
    algorithm. The polynomials correspond to the rows of the LLL-reduce
396 247 storres
    reduced base that comply with the Coppersmith condition.
397 247 storres
    """
398 247 storres
    #@par Changes from runSLZ-113.sage
399 247 storres
    # LLL reduction is not performed on the matrix itself but rather on the
400 247 storres
    # product of the matrix with a uniform random matrix.
401 247 storres
    # The reduced matrix obtained is discarded but the transformation matrix
402 247 storres
    # obtained is used to multiply the original matrix in order to reduced it.
403 247 storres
    # If a sufficient level of reduction is obtained, we stop here. If not
404 247 storres
    # the product matrix obtained above is LLL reduced. But as it has been
405 247 storres
    # pre-reduced at the above step, reduction is supposed to be much faster.
406 247 storres
    #
407 247 storres
    # Arguments check.
408 247 storres
    if iBound == 0 or tBound == 0:
409 247 storres
        return None
410 247 storres
    # End arguments check.
411 247 storres
    nAtAlpha = N^alpha
412 247 storres
    ## Building polynomials for matrix.
413 247 storres
    polyRing   = inputPolynomial.parent()
414 247 storres
    # Whatever the 2 variables are actually called, we call them
415 247 storres
    # 'i' and 't' in all the variable names.
416 247 storres
    (iVariable, tVariable) = inputPolynomial.variables()[:2]
417 247 storres
    #print polyVars[0], type(polyVars[0])
418 247 storres
    initialPolynomial = inputPolynomial.subs({iVariable:iVariable * iBound,
419 247 storres
                                              tVariable:tVariable * tBound})
420 247 storres
    if debug:
421 247 storres
        polynomialsList = \
422 247 storres
            spo_polynomial_to_polynomials_list_8(initialPolynomial,
423 247 storres
                                                 alpha,
424 247 storres
                                                 N,
425 247 storres
                                                 iBound,
426 247 storres
                                                 tBound,
427 247 storres
                                                 20)
428 247 storres
    else:
429 247 storres
        polynomialsList = \
430 247 storres
            spo_polynomial_to_polynomials_list_8(initialPolynomial,
431 247 storres
                                                 alpha,
432 247 storres
                                                 N,
433 247 storres
                                                 iBound,
434 247 storres
                                                 tBound,
435 247 storres
                                                 0)
436 247 storres
    #print "Polynomials list:", polynomialsList
437 247 storres
    ## Building the proto matrix.
438 247 storres
    knownMonomials = []
439 247 storres
    protoMatrix    = []
440 247 storres
    if debug:
441 247 storres
        for poly in polynomialsList:
442 247 storres
            spo_add_polynomial_coeffs_to_matrix_row(poly,
443 247 storres
                                                    knownMonomials,
444 247 storres
                                                    protoMatrix,
445 247 storres
                                                    20)
446 247 storres
    else:
447 247 storres
        for poly in polynomialsList:
448 247 storres
            spo_add_polynomial_coeffs_to_matrix_row(poly,
449 247 storres
                                                    knownMonomials,
450 247 storres
                                                    protoMatrix,
451 247 storres
                                                    0)
452 247 storres
    matrixToReduce = spo_proto_to_row_matrix(protoMatrix)
453 247 storres
    #print matrixToReduce
454 247 storres
    ## Reduction and checking.
455 247 storres
    ### Reduction with projection
456 249 storres
    (reducedMatrixStep1, reductionMatrixStep1) = \
457 249 storres
         slz_reduce_lll_proj(matrixToReduce,16)
458 247 storres
    #print "Reduced matrix:"
459 249 storres
    #print reducedMatrixStep1
460 247 storres
    #for row in reducedMatrix.rows():
461 247 storres
    #    print row
462 247 storres
    monomialsCount     = len(knownMonomials)
463 247 storres
    monomialsCountSqrt = sqrt(monomialsCount)
464 247 storres
    #print "Monomials count:", monomialsCount, monomialsCountSqrt.n()
465 247 storres
    #print reducedMatrix
466 247 storres
    ## Check the Coppersmith condition for each row and build the reduced
467 247 storres
    #  polynomials.
468 247 storres
    ccReducedPolynomialsList = []
469 249 storres
    for row in reducedMatrixStep1.rows():
470 249 storres
        l2Norm = row.norm(2)
471 249 storres
        if (l2Norm * monomialsCountSqrt) < nAtAlpha:
472 249 storres
            #print (l2Norm * monomialsCountSqrt).n()
473 249 storres
            #print l2Norm.n()
474 249 storres
            ccReducedPolynomial = \
475 249 storres
                slz_compute_reduced_polynomial(row,
476 249 storres
                                               knownMonomials,
477 249 storres
                                               iVariable,
478 249 storres
                                               iBound,
479 249 storres
                                               tVariable,
480 249 storres
                                               tBound)
481 249 storres
            if not ccReducedPolynomial is None:
482 249 storres
                ccReducedPolynomialsList.append(ccReducedPolynomial)
483 249 storres
        else:
484 249 storres
            #print l2Norm.n() , ">", nAtAlpha
485 249 storres
            pass
486 279 storres
        # End if
487 279 storres
    # End for.
488 249 storres
    if len(ccReducedPolynomialsList) < 2: # Insufficient reduction.
489 249 storres
        print "Less than 2 Coppersmith condition compliant vectors."
490 249 storres
        print "Extra reduction starting..."
491 279 storres
        reducedMatrixStep2 = reducedMatrixStep1.LLL(algorithm='fpLLL:wrapper')
492 279 storres
        ## Create a fresh reduced polynomials list.
493 279 storres
        ccReducedPolynomialsList = []
494 279 storres
        for row in reducedMatrixStep2.rows():
495 279 storres
            l2Norm = row.norm(2)
496 279 storres
            if (l2Norm * monomialsCountSqrt) < nAtAlpha:
497 279 storres
                #print (l2Norm * monomialsCountSqrt).n()
498 279 storres
                #print l2Norm.n()
499 279 storres
                ccReducedPolynomial = \
500 279 storres
                    slz_compute_reduced_polynomial(row,
501 279 storres
                                                   knownMonomials,
502 279 storres
                                                   iVariable,
503 279 storres
                                                   iBound,
504 279 storres
                                                   tVariable,
505 279 storres
                                                   tBound)
506 279 storres
                if not ccReducedPolynomial is None:
507 279 storres
                    ccReducedPolynomialsList.append(ccReducedPolynomial)
508 279 storres
        # End for.
509 279 storres
    else: # At least 2 small norm enough vectors from reducedMatrixStep2.
510 253 storres
        print "First step of reduction afforded enough vectors"
511 279 storres
    return ccReducedPolynomialsList
512 249 storres
    #print ccReducedPolynomialsList
513 249 storres
    ## Check again the Coppersmith condition for each row and build the reduced
514 249 storres
    #  polynomials.
515 249 storres
    ccReducedPolynomialsList = []
516 247 storres
    for row in reducedMatrix.rows():
517 247 storres
        l2Norm = row.norm(2)
518 247 storres
        if (l2Norm * monomialsCountSqrt) < nAtAlpha:
519 247 storres
            #print (l2Norm * monomialsCountSqrt).n()
520 247 storres
            #print l2Norm.n()
521 247 storres
            ccReducedPolynomial = \
522 247 storres
                slz_compute_reduced_polynomial(row,
523 247 storres
                                               knownMonomials,
524 247 storres
                                               iVariable,
525 247 storres
                                               iBound,
526 247 storres
                                               tVariable,
527 247 storres
                                               tBound)
528 247 storres
            if not ccReducedPolynomial is None:
529 247 storres
                ccReducedPolynomialsList.append(ccReducedPolynomial)
530 247 storres
        else:
531 247 storres
            #print l2Norm.n() , ">", nAtAlpha
532 247 storres
            pass
533 249 storres
    if len(ccReducedPolynomialsList) < 2: # Insufficient reduction.
534 253 storres
        print "Less than 2 Coppersmith condition compliant vectors after extra reduction."
535 247 storres
        return ()
536 249 storres
    else:
537 249 storres
        return ccReducedPolynomialsList
538 247 storres
# End slz_compute_coppersmith_reduced_polynomials_proj
539 277 storres
#
540 277 storres
def slz_compute_weak_coppersmith_reduced_polynomials_proj_02(inputPolynomial,
541 277 storres
                                                             alpha,
542 277 storres
                                                             N,
543 277 storres
                                                             iBound,
544 277 storres
                                                             tBound,
545 277 storres
                                                             debug = False):
546 277 storres
    """
547 277 storres
    For a given set of arguments (see below), compute a list
548 277 storres
    of "reduced polynomials" that could be used to compute roots
549 277 storres
    of the inputPolynomial.
550 277 storres
    INPUT:
551 277 storres
552 277 storres
    - "inputPolynomial" -- (no default) a bivariate integer polynomial;
553 277 storres
    - "alpha" -- the alpha parameter of the Coppersmith algorithm;
554 277 storres
    - "N" -- the modulus;
555 277 storres
    - "iBound" -- the bound on the first variable;
556 277 storres
    - "tBound" -- the bound on the second variable.
557 277 storres
558 277 storres
    OUTPUT:
559 277 storres
560 277 storres
    A list of bivariate integer polynomial obtained using the Coppersmith
561 277 storres
    algorithm. The polynomials correspond to the rows of the LLL-reduce
562 277 storres
    reduced base that comply with the weak version of Coppersmith condition.
563 277 storres
    """
564 277 storres
    #@par Changes from runSLZ-113.sage
565 277 storres
    # LLL reduction is not performed on the matrix itself but rather on the
566 277 storres
    # product of the matrix with a uniform random matrix.
567 277 storres
    # The reduced matrix obtained is discarded but the transformation matrix
568 277 storres
    # obtained is used to multiply the original matrix in order to reduced it.
569 277 storres
    # If a sufficient level of reduction is obtained, we stop here. If not
570 277 storres
    # the product matrix obtained above is LLL reduced. But as it has been
571 277 storres
    # pre-reduced at the above step, reduction is supposed to be much faster.
572 277 storres
    #
573 277 storres
    # Arguments check.
574 277 storres
    if iBound == 0 or tBound == 0:
575 277 storres
        return None
576 277 storres
    # End arguments check.
577 277 storres
    nAtAlpha = N^alpha
578 277 storres
    ## Building polynomials for matrix.
579 277 storres
    polyRing   = inputPolynomial.parent()
580 277 storres
    # Whatever the 2 variables are actually called, we call them
581 277 storres
    # 'i' and 't' in all the variable names.
582 277 storres
    (iVariable, tVariable) = inputPolynomial.variables()[:2]
583 277 storres
    #print polyVars[0], type(polyVars[0])
584 277 storres
    initialPolynomial = inputPolynomial.subs({iVariable:iVariable * iBound,
585 277 storres
                                              tVariable:tVariable * tBound})
586 277 storres
    if debug:
587 277 storres
        polynomialsList = \
588 277 storres
            spo_polynomial_to_polynomials_list_8(initialPolynomial,
589 277 storres
                                                 alpha,
590 277 storres
                                                 N,
591 277 storres
                                                 iBound,
592 277 storres
                                                 tBound,
593 277 storres
                                                 20)
594 277 storres
    else:
595 277 storres
        polynomialsList = \
596 277 storres
            spo_polynomial_to_polynomials_list_8(initialPolynomial,
597 277 storres
                                                 alpha,
598 277 storres
                                                 N,
599 277 storres
                                                 iBound,
600 277 storres
                                                 tBound,
601 277 storres
                                                 0)
602 277 storres
    #print "Polynomials list:", polynomialsList
603 277 storres
    ## Building the proto matrix.
604 277 storres
    knownMonomials = []
605 277 storres
    protoMatrix    = []
606 277 storres
    if debug:
607 277 storres
        for poly in polynomialsList:
608 277 storres
            spo_add_polynomial_coeffs_to_matrix_row(poly,
609 277 storres
                                                    knownMonomials,
610 277 storres
                                                    protoMatrix,
611 277 storres
                                                    20)
612 277 storres
    else:
613 277 storres
        for poly in polynomialsList:
614 277 storres
            spo_add_polynomial_coeffs_to_matrix_row(poly,
615 277 storres
                                                    knownMonomials,
616 277 storres
                                                    protoMatrix,
617 277 storres
                                                    0)
618 277 storres
    matrixToReduce = spo_proto_to_row_matrix(protoMatrix)
619 277 storres
    #print matrixToReduce
620 277 storres
    ## Reduction and checking.
621 277 storres
    ### Reduction with projection
622 277 storres
    (reducedMatrixStep1, reductionMatrixStep1) = \
623 277 storres
         slz_reduce_lll_proj_02(matrixToReduce,16)
624 277 storres
    #print "Reduced matrix:"
625 277 storres
    #print reducedMatrixStep1
626 277 storres
    #for row in reducedMatrix.rows():
627 277 storres
    #    print row
628 277 storres
    monomialsCount     = len(knownMonomials)
629 277 storres
    monomialsCountSqrt = sqrt(monomialsCount)
630 277 storres
    #print "Monomials count:", monomialsCount, monomialsCountSqrt.n()
631 277 storres
    #print reducedMatrix
632 277 storres
    ## Check the Coppersmith condition for each row and build the reduced
633 277 storres
    #  polynomials.
634 277 storres
    ccReducedPolynomialsList = []
635 277 storres
    for row in reducedMatrixStep1.rows():
636 277 storres
        l1Norm = row.norm(1)
637 277 storres
        l2Norm = row.norm(2)
638 277 storres
        if l2Norm * monomialsCountSqrt < l1Norm:
639 277 storres
            print "l1norm is smaller than l2norm*sqrt(w)."
640 277 storres
        else:
641 277 storres
            print "l1norm is NOT smaller than l2norm*sqrt(w)."
642 277 storres
            print (l2Norm * monomialsCountSqrt).n(), 'vs ', l1Norm.n()
643 277 storres
        if l1Norm < nAtAlpha:
644 277 storres
            #print l2Norm.n()
645 277 storres
            ccReducedPolynomial = \
646 277 storres
                slz_compute_reduced_polynomial(row,
647 277 storres
                                               knownMonomials,
648 277 storres
                                               iVariable,
649 277 storres
                                               iBound,
650 277 storres
                                               tVariable,
651 277 storres
                                               tBound)
652 277 storres
            if not ccReducedPolynomial is None:
653 277 storres
                ccReducedPolynomialsList.append(ccReducedPolynomial)
654 277 storres
        else:
655 277 storres
            #print l2Norm.n() , ">", nAtAlpha
656 277 storres
            pass
657 277 storres
    if len(ccReducedPolynomialsList) < 2: # Insufficient reduction.
658 277 storres
        print "Less than 2 Coppersmith condition compliant vectors."
659 277 storres
        print "Extra reduction starting..."
660 277 storres
        reducedMatrix = reducedMatrixStep1.LLL(algorithm='fpLLL:wrapper')
661 277 storres
        ### If uncommented, the following statement avoids performing
662 277 storres
        #   an actual LLL reduction. This allows for demonstrating
663 277 storres
        #   the behavior of our pseudo-reduction alone.
664 277 storres
        #return ()
665 277 storres
    else:
666 277 storres
        print "First step of reduction afforded enough vectors"
667 277 storres
        return ccReducedPolynomialsList
668 277 storres
    #print ccReducedPolynomialsList
669 277 storres
    ## Check again the Coppersmith condition for each row and build the reduced
670 277 storres
    #  polynomials.
671 277 storres
    ccReducedPolynomialsList = []
672 277 storres
    for row in reducedMatrix.rows():
673 277 storres
        l2Norm = row.norm(2)
674 277 storres
        if (l2Norm * monomialsCountSqrt) < nAtAlpha:
675 277 storres
            #print (l2Norm * monomialsCountSqrt).n()
676 277 storres
            #print l2Norm.n()
677 277 storres
            ccReducedPolynomial = \
678 277 storres
                slz_compute_reduced_polynomial(row,
679 277 storres
                                               knownMonomials,
680 277 storres
                                               iVariable,
681 277 storres
                                               iBound,
682 277 storres
                                               tVariable,
683 277 storres
                                               tBound)
684 277 storres
            if not ccReducedPolynomial is None:
685 277 storres
                ccReducedPolynomialsList.append(ccReducedPolynomial)
686 277 storres
        else:
687 277 storres
            #print l2Norm.n() , ">", nAtAlpha
688 277 storres
            pass
689 277 storres
    if len(ccReducedPolynomialsList) < 2: # Insufficient reduction.
690 277 storres
        print "Less than 2 Coppersmith condition compliant vectors after extra reduction."
691 277 storres
        return ()
692 277 storres
    else:
693 277 storres
        return ccReducedPolynomialsList
694 277 storres
# End slz_compute_coppersmith_reduced_polynomials_proj_02
695 277 storres
#
696 277 storres
def slz_compute_coppersmith_reduced_polynomials_proj(inputPolynomial,
697 277 storres
                                                     alpha,
698 277 storres
                                                     N,
699 277 storres
                                                     iBound,
700 277 storres
                                                     tBound,
701 277 storres
                                                     debug = False):
702 277 storres
    """
703 277 storres
    For a given set of arguments (see below), compute a list
704 277 storres
    of "reduced polynomials" that could be used to compute roots
705 277 storres
    of the inputPolynomial.
706 277 storres
    INPUT:
707 277 storres
708 277 storres
    - "inputPolynomial" -- (no default) a bivariate integer polynomial;
709 277 storres
    - "alpha" -- the alpha parameter of the Coppersmith algorithm;
710 277 storres
    - "N" -- the modulus;
711 277 storres
    - "iBound" -- the bound on the first variable;
712 277 storres
    - "tBound" -- the bound on the second variable.
713 277 storres
714 277 storres
    OUTPUT:
715 277 storres
716 277 storres
    A list of bivariate integer polynomial obtained using the Coppersmith
717 277 storres
    algorithm. The polynomials correspond to the rows of the LLL-reduce
718 277 storres
    reduced base that comply with the Coppersmith condition.
719 277 storres
    """
720 277 storres
    #@par Changes from runSLZ-113.sage
721 277 storres
    # LLL reduction is not performed on the matrix itself but rather on the
722 277 storres
    # product of the matrix with a uniform random matrix.
723 277 storres
    # The reduced matrix obtained is discarded but the transformation matrix
724 277 storres
    # obtained is used to multiply the original matrix in order to reduced it.
725 277 storres
    # If a sufficient level of reduction is obtained, we stop here. If not
726 277 storres
    # the product matrix obtained above is LLL reduced. But as it has been
727 277 storres
    # pre-reduced at the above step, reduction is supposed to be much faster.
728 277 storres
    #
729 277 storres
    # Arguments check.
730 277 storres
    if iBound == 0 or tBound == 0:
731 277 storres
        return None
732 277 storres
    # End arguments check.
733 277 storres
    nAtAlpha = N^alpha
734 277 storres
    ## Building polynomials for matrix.
735 277 storres
    polyRing   = inputPolynomial.parent()
736 277 storres
    # Whatever the 2 variables are actually called, we call them
737 277 storres
    # 'i' and 't' in all the variable names.
738 277 storres
    (iVariable, tVariable) = inputPolynomial.variables()[:2]
739 277 storres
    #print polyVars[0], type(polyVars[0])
740 277 storres
    initialPolynomial = inputPolynomial.subs({iVariable:iVariable * iBound,
741 277 storres
                                              tVariable:tVariable * tBound})
742 277 storres
    if debug:
743 277 storres
        polynomialsList = \
744 277 storres
            spo_polynomial_to_polynomials_list_8(initialPolynomial,
745 277 storres
                                                 alpha,
746 277 storres
                                                 N,
747 277 storres
                                                 iBound,
748 277 storres
                                                 tBound,
749 277 storres
                                                 20)
750 277 storres
    else:
751 277 storres
        polynomialsList = \
752 277 storres
            spo_polynomial_to_polynomials_list_8(initialPolynomial,
753 277 storres
                                                 alpha,
754 277 storres
                                                 N,
755 277 storres
                                                 iBound,
756 277 storres
                                                 tBound,
757 277 storres
                                                 0)
758 277 storres
    #print "Polynomials list:", polynomialsList
759 277 storres
    ## Building the proto matrix.
760 277 storres
    knownMonomials = []
761 277 storres
    protoMatrix    = []
762 277 storres
    if debug:
763 277 storres
        for poly in polynomialsList:
764 277 storres
            spo_add_polynomial_coeffs_to_matrix_row(poly,
765 277 storres
                                                    knownMonomials,
766 277 storres
                                                    protoMatrix,
767 277 storres
                                                    20)
768 277 storres
    else:
769 277 storres
        for poly in polynomialsList:
770 277 storres
            spo_add_polynomial_coeffs_to_matrix_row(poly,
771 277 storres
                                                    knownMonomials,
772 277 storres
                                                    protoMatrix,
773 277 storres
                                                    0)
774 277 storres
    matrixToReduce = spo_proto_to_row_matrix(protoMatrix)
775 277 storres
    #print matrixToReduce
776 277 storres
    ## Reduction and checking.
777 277 storres
    ### Reduction with projection
778 277 storres
    (reducedMatrixStep1, reductionMatrixStep1) = \
779 277 storres
         slz_reduce_lll_proj(matrixToReduce,16)
780 277 storres
    #print "Reduced matrix:"
781 277 storres
    #print reducedMatrixStep1
782 277 storres
    #for row in reducedMatrix.rows():
783 277 storres
    #    print row
784 277 storres
    monomialsCount     = len(knownMonomials)
785 277 storres
    monomialsCountSqrt = sqrt(monomialsCount)
786 277 storres
    #print "Monomials count:", monomialsCount, monomialsCountSqrt.n()
787 277 storres
    #print reducedMatrix
788 277 storres
    ## Check the Coppersmith condition for each row and build the reduced
789 277 storres
    #  polynomials.
790 277 storres
    ccReducedPolynomialsList = []
791 277 storres
    for row in reducedMatrixStep1.rows():
792 277 storres
        l2Norm = row.norm(2)
793 277 storres
        if (l2Norm * monomialsCountSqrt) < nAtAlpha:
794 277 storres
            #print (l2Norm * monomialsCountSqrt).n()
795 277 storres
            #print l2Norm.n()
796 277 storres
            ccReducedPolynomial = \
797 277 storres
                slz_compute_reduced_polynomial(row,
798 277 storres
                                               knownMonomials,
799 277 storres
                                               iVariable,
800 277 storres
                                               iBound,
801 277 storres
                                               tVariable,
802 277 storres
                                               tBound)
803 277 storres
            if not ccReducedPolynomial is None:
804 277 storres
                ccReducedPolynomialsList.append(ccReducedPolynomial)
805 277 storres
        else:
806 277 storres
            #print l2Norm.n() , ">", nAtAlpha
807 277 storres
            pass
808 277 storres
    if len(ccReducedPolynomialsList) < 2: # Insufficient reduction.
809 277 storres
        print "Less than 2 Coppersmith condition compliant vectors."
810 277 storres
        print "Extra reduction starting..."
811 277 storres
        reducedMatrix = reducedMatrixStep1.LLL(algorithm='fpLLL:wrapper')
812 277 storres
        ### If uncommented, the following statement avoids performing
813 277 storres
        #   an actual LLL reduction. This allows for demonstrating
814 277 storres
        #   the behavior of our pseudo-reduction alone.
815 277 storres
        #return ()
816 277 storres
    else:
817 277 storres
        print "First step of reduction afforded enough vectors"
818 277 storres
        return ccReducedPolynomialsList
819 277 storres
    #print ccReducedPolynomialsList
820 277 storres
    ## Check again the Coppersmith condition for each row and build the reduced
821 277 storres
    #  polynomials.
822 277 storres
    ccReducedPolynomialsList = []
823 277 storres
    for row in reducedMatrix.rows():
824 277 storres
        l2Norm = row.norm(2)
825 277 storres
        if (l2Norm * monomialsCountSqrt) < nAtAlpha:
826 277 storres
            #print (l2Norm * monomialsCountSqrt).n()
827 277 storres
            #print l2Norm.n()
828 277 storres
            ccReducedPolynomial = \
829 277 storres
                slz_compute_reduced_polynomial(row,
830 277 storres
                                               knownMonomials,
831 277 storres
                                               iVariable,
832 277 storres
                                               iBound,
833 277 storres
                                               tVariable,
834 277 storres
                                               tBound)
835 277 storres
            if not ccReducedPolynomial is None:
836 277 storres
                ccReducedPolynomialsList.append(ccReducedPolynomial)
837 277 storres
        else:
838 277 storres
            #print l2Norm.n() , ">", nAtAlpha
839 277 storres
            pass
840 277 storres
    if len(ccReducedPolynomialsList) < 2: # Insufficient reduction.
841 277 storres
        print "Less than 2 Coppersmith condition compliant vectors after extra reduction."
842 277 storres
        return ()
843 277 storres
    else:
844 277 storres
        return ccReducedPolynomialsList
845 277 storres
# End slz_compute_coppersmith_reduced_polynomials_proj
846 274 storres
def slz_compute_weak_coppersmith_reduced_polynomials_proj(inputPolynomial,
847 274 storres
                                                          alpha,
848 274 storres
                                                          N,
849 274 storres
                                                          iBound,
850 274 storres
                                                          tBound,
851 274 storres
                                                          debug = False):
852 274 storres
    """
853 274 storres
    For a given set of arguments (see below), compute a list
854 274 storres
    of "reduced polynomials" that could be used to compute roots
855 274 storres
    of the inputPolynomial.
856 274 storres
    INPUT:
857 274 storres
858 274 storres
    - "inputPolynomial" -- (no default) a bivariate integer polynomial;
859 274 storres
    - "alpha" -- the alpha parameter of the Coppersmith algorithm;
860 274 storres
    - "N" -- the modulus;
861 274 storres
    - "iBound" -- the bound on the first variable;
862 274 storres
    - "tBound" -- the bound on the second variable.
863 274 storres
864 274 storres
    OUTPUT:
865 274 storres
866 274 storres
    A list of bivariate integer polynomial obtained using the Coppersmith
867 274 storres
    algorithm. The polynomials correspond to the rows of the LLL-reduce
868 274 storres
    reduced base that comply with the weak version of Coppersmith condition.
869 274 storres
    """
870 274 storres
    #@par Changes from runSLZ-113.sage
871 274 storres
    # LLL reduction is not performed on the matrix itself but rather on the
872 274 storres
    # product of the matrix with a uniform random matrix.
873 274 storres
    # The reduced matrix obtained is discarded but the transformation matrix
874 274 storres
    # obtained is used to multiply the original matrix in order to reduced it.
875 274 storres
    # If a sufficient level of reduction is obtained, we stop here. If not
876 274 storres
    # the product matrix obtained above is LLL reduced. But as it has been
877 274 storres
    # pre-reduced at the above step, reduction is supposed to be much faster.
878 274 storres
    #
879 274 storres
    # Arguments check.
880 274 storres
    if iBound == 0 or tBound == 0:
881 274 storres
        return None
882 274 storres
    # End arguments check.
883 274 storres
    nAtAlpha = N^alpha
884 274 storres
    ## Building polynomials for matrix.
885 274 storres
    polyRing   = inputPolynomial.parent()
886 274 storres
    # Whatever the 2 variables are actually called, we call them
887 274 storres
    # 'i' and 't' in all the variable names.
888 274 storres
    (iVariable, tVariable) = inputPolynomial.variables()[:2]
889 274 storres
    #print polyVars[0], type(polyVars[0])
890 274 storres
    initialPolynomial = inputPolynomial.subs({iVariable:iVariable * iBound,
891 274 storres
                                              tVariable:tVariable * tBound})
892 274 storres
    if debug:
893 274 storres
        polynomialsList = \
894 274 storres
            spo_polynomial_to_polynomials_list_8(initialPolynomial,
895 274 storres
                                                 alpha,
896 274 storres
                                                 N,
897 274 storres
                                                 iBound,
898 274 storres
                                                 tBound,
899 274 storres
                                                 20)
900 274 storres
    else:
901 274 storres
        polynomialsList = \
902 274 storres
            spo_polynomial_to_polynomials_list_8(initialPolynomial,
903 274 storres
                                                 alpha,
904 274 storres
                                                 N,
905 274 storres
                                                 iBound,
906 274 storres
                                                 tBound,
907 274 storres
                                                 0)
908 274 storres
    #print "Polynomials list:", polynomialsList
909 274 storres
    ## Building the proto matrix.
910 274 storres
    knownMonomials = []
911 274 storres
    protoMatrix    = []
912 274 storres
    if debug:
913 274 storres
        for poly in polynomialsList:
914 274 storres
            spo_add_polynomial_coeffs_to_matrix_row(poly,
915 274 storres
                                                    knownMonomials,
916 274 storres
                                                    protoMatrix,
917 274 storres
                                                    20)
918 274 storres
    else:
919 274 storres
        for poly in polynomialsList:
920 274 storres
            spo_add_polynomial_coeffs_to_matrix_row(poly,
921 274 storres
                                                    knownMonomials,
922 274 storres
                                                    protoMatrix,
923 274 storres
                                                    0)
924 274 storres
    matrixToReduce = spo_proto_to_row_matrix(protoMatrix)
925 274 storres
    #print matrixToReduce
926 274 storres
    ## Reduction and checking.
927 274 storres
    ### Reduction with projection
928 274 storres
    (reducedMatrixStep1, reductionMatrixStep1) = \
929 274 storres
         slz_reduce_lll_proj(matrixToReduce,16)
930 274 storres
    #print "Reduced matrix:"
931 274 storres
    #print reducedMatrixStep1
932 274 storres
    #for row in reducedMatrix.rows():
933 274 storres
    #    print row
934 274 storres
    monomialsCount     = len(knownMonomials)
935 274 storres
    monomialsCountSqrt = sqrt(monomialsCount)
936 274 storres
    #print "Monomials count:", monomialsCount, monomialsCountSqrt.n()
937 274 storres
    #print reducedMatrix
938 274 storres
    ## Check the Coppersmith condition for each row and build the reduced
939 274 storres
    #  polynomials.
940 274 storres
    ccReducedPolynomialsList = []
941 274 storres
    for row in reducedMatrixStep1.rows():
942 274 storres
        l1Norm = row.norm(1)
943 274 storres
        l2Norm = row.norm(2)
944 274 storres
        if l2Norm * monomialsCountSqrt < l1Norm:
945 274 storres
            print "l1norm is smaller than l2norm*sqrt(w)."
946 274 storres
        else:
947 274 storres
            print "l1norm is NOT smaller than l2norm*sqrt(w)."
948 274 storres
            print (l2Norm * monomialsCountSqrt).n(), 'vs ', l1Norm.n()
949 274 storres
        if l1Norm < nAtAlpha:
950 274 storres
            #print l2Norm.n()
951 274 storres
            ccReducedPolynomial = \
952 274 storres
                slz_compute_reduced_polynomial(row,
953 274 storres
                                               knownMonomials,
954 274 storres
                                               iVariable,
955 274 storres
                                               iBound,
956 274 storres
                                               tVariable,
957 274 storres
                                               tBound)
958 274 storres
            if not ccReducedPolynomial is None:
959 274 storres
                ccReducedPolynomialsList.append(ccReducedPolynomial)
960 274 storres
        else:
961 274 storres
            #print l2Norm.n() , ">", nAtAlpha
962 274 storres
            pass
963 274 storres
    if len(ccReducedPolynomialsList) < 2: # Insufficient reduction.
964 274 storres
        print "Less than 2 Coppersmith condition compliant vectors."
965 274 storres
        print "Extra reduction starting..."
966 274 storres
        reducedMatrix = reducedMatrixStep1.LLL(algorithm='fpLLL:wrapper')
967 274 storres
        ### If uncommented, the following statement avoids performing
968 274 storres
        #   an actual LLL reduction. This allows for demonstrating
969 274 storres
        #   the behavior of our pseudo-reduction alone.
970 274 storres
        #return ()
971 274 storres
    else:
972 274 storres
        print "First step of reduction afforded enough vectors"
973 274 storres
        return ccReducedPolynomialsList
974 274 storres
    #print ccReducedPolynomialsList
975 274 storres
    ## Check again the Coppersmith condition for each row and build the reduced
976 274 storres
    #  polynomials.
977 274 storres
    ccReducedPolynomialsList = []
978 274 storres
    for row in reducedMatrix.rows():
979 274 storres
        l2Norm = row.norm(2)
980 274 storres
        if (l2Norm * monomialsCountSqrt) < nAtAlpha:
981 274 storres
            #print (l2Norm * monomialsCountSqrt).n()
982 274 storres
            #print l2Norm.n()
983 274 storres
            ccReducedPolynomial = \
984 274 storres
                slz_compute_reduced_polynomial(row,
985 274 storres
                                               knownMonomials,
986 274 storres
                                               iVariable,
987 274 storres
                                               iBound,
988 274 storres
                                               tVariable,
989 274 storres
                                               tBound)
990 274 storres
            if not ccReducedPolynomial is None:
991 274 storres
                ccReducedPolynomialsList.append(ccReducedPolynomial)
992 274 storres
        else:
993 274 storres
            #print l2Norm.n() , ">", nAtAlpha
994 274 storres
            pass
995 274 storres
    if len(ccReducedPolynomialsList) < 2: # Insufficient reduction.
996 274 storres
        print "Less than 2 Coppersmith condition compliant vectors after extra reduction."
997 274 storres
        return ()
998 274 storres
    else:
999 274 storres
        return ccReducedPolynomialsList
1000 277 storres
# End slz_compute_coppersmith_reduced_polynomials_proj2
1001 247 storres
#
1002 212 storres
def slz_compute_coppersmith_reduced_polynomials_with_lattice_volume(inputPolynomial,
1003 212 storres
                                                                    alpha,
1004 212 storres
                                                                    N,
1005 212 storres
                                                                    iBound,
1006 229 storres
                                                                    tBound,
1007 229 storres
                                                                    debug = False):
1008 212 storres
    """
1009 212 storres
    For a given set of arguments (see below), compute a list
1010 212 storres
    of "reduced polynomials" that could be used to compute roots
1011 212 storres
    of the inputPolynomial.
1012 212 storres
    Print the volume of the initial basis as well.
1013 212 storres
    INPUT:
1014 212 storres
1015 212 storres
    - "inputPolynomial" -- (no default) a bivariate integer polynomial;
1016 212 storres
    - "alpha" -- the alpha parameter of the Coppersmith algorithm;
1017 212 storres
    - "N" -- the modulus;
1018 212 storres
    - "iBound" -- the bound on the first variable;
1019 212 storres
    - "tBound" -- the bound on the second variable.
1020 212 storres
1021 212 storres
    OUTPUT:
1022 212 storres
1023 212 storres
    A list of bivariate integer polynomial obtained using the Coppersmith
1024 212 storres
    algorithm. The polynomials correspond to the rows of the LLL-reduce
1025 212 storres
    reduced base that comply with the Coppersmith condition.
1026 212 storres
    """
1027 212 storres
    # Arguments check.
1028 212 storres
    if iBound == 0 or tBound == 0:
1029 212 storres
        return None
1030 212 storres
    # End arguments check.
1031 212 storres
    nAtAlpha = N^alpha
1032 229 storres
    if debug:
1033 229 storres
        print "N at alpha:", nAtAlpha
1034 212 storres
    ## Building polynomials for matrix.
1035 212 storres
    polyRing   = inputPolynomial.parent()
1036 212 storres
    # Whatever the 2 variables are actually called, we call them
1037 212 storres
    # 'i' and 't' in all the variable names.
1038 212 storres
    (iVariable, tVariable) = inputPolynomial.variables()[:2]
1039 212 storres
    #print polyVars[0], type(polyVars[0])
1040 212 storres
    initialPolynomial = inputPolynomial.subs({iVariable:iVariable * iBound,
1041 212 storres
                                              tVariable:tVariable * tBound})
1042 212 storres
##    polynomialsList = \
1043 212 storres
##        spo_polynomial_to_polynomials_list_8(initialPolynomial,
1044 212 storres
##        spo_polynomial_to_polynomials_list_5(initialPolynomial,
1045 212 storres
    polynomialsList = \
1046 212 storres
        spo_polynomial_to_polynomials_list_5(initialPolynomial,
1047 212 storres
                                             alpha,
1048 212 storres
                                             N,
1049 212 storres
                                             iBound,
1050 212 storres
                                             tBound,
1051 212 storres
                                             0)
1052 212 storres
    #print "Polynomials list:", polynomialsList
1053 212 storres
    ## Building the proto matrix.
1054 212 storres
    knownMonomials = []
1055 212 storres
    protoMatrix    = []
1056 212 storres
    for poly in polynomialsList:
1057 212 storres
        spo_add_polynomial_coeffs_to_matrix_row(poly,
1058 212 storres
                                                knownMonomials,
1059 212 storres
                                                protoMatrix,
1060 212 storres
                                                0)
1061 212 storres
    matrixToReduce = spo_proto_to_row_matrix(protoMatrix)
1062 212 storres
    matrixToReduceTranspose = matrixToReduce.transpose()
1063 212 storres
    squareMatrix = matrixToReduce * matrixToReduceTranspose
1064 212 storres
    squareMatDet = det(squareMatrix)
1065 212 storres
    latticeVolume = sqrt(squareMatDet)
1066 212 storres
    print "Lattice volume:", latticeVolume.n()
1067 212 storres
    print "Lattice volume / N:", (latticeVolume/N).n()
1068 212 storres
    #print matrixToReduce
1069 212 storres
    ## Reduction and checking.
1070 212 storres
    ## S.T. changed 'fp' to None as of Sage 6.6 complying to
1071 212 storres
    #  error message issued when previous code was used.
1072 212 storres
    #reducedMatrix = matrixToReduce.LLL(fp='fp')
1073 212 storres
    reductionTimeStart = cputime()
1074 212 storres
    reducedMatrix = matrixToReduce.LLL(fp=None)
1075 212 storres
    reductionTime = cputime(reductionTimeStart)
1076 212 storres
    print "Reduction time:", reductionTime
1077 212 storres
    isLLLReduced  = reducedMatrix.is_LLL_reduced()
1078 212 storres
    if not isLLLReduced:
1079 229 storres
       return None
1080 229 storres
    #
1081 229 storres
    if debug:
1082 229 storres
        matrixFile = file('/tmp/reducedMatrix.txt', 'w')
1083 229 storres
        for row in reducedMatrix.rows():
1084 229 storres
            matrixFile.write(str(row) + "\n")
1085 229 storres
        matrixFile.close()
1086 229 storres
    #
1087 212 storres
    monomialsCount     = len(knownMonomials)
1088 212 storres
    monomialsCountSqrt = sqrt(monomialsCount)
1089 212 storres
    #print "Monomials count:", monomialsCount, monomialsCountSqrt.n()
1090 212 storres
    #print reducedMatrix
1091 212 storres
    ## Check the Coppersmith condition for each row and build the reduced
1092 212 storres
    #  polynomials.
1093 229 storres
    ccVectorsCount = 0
1094 212 storres
    ccReducedPolynomialsList = []
1095 212 storres
    for row in reducedMatrix.rows():
1096 212 storres
        l2Norm = row.norm(2)
1097 212 storres
        if (l2Norm * monomialsCountSqrt) < nAtAlpha:
1098 212 storres
            #print (l2Norm * monomialsCountSqrt).n()
1099 212 storres
            #print l2Norm.n()
1100 229 storres
            ccVectorsCount +=1
1101 212 storres
            ccReducedPolynomial = \
1102 212 storres
                slz_compute_reduced_polynomial(row,
1103 212 storres
                                               knownMonomials,
1104 212 storres
                                               iVariable,
1105 212 storres
                                               iBound,
1106 212 storres
                                               tVariable,
1107 212 storres
                                               tBound)
1108 212 storres
            if not ccReducedPolynomial is None:
1109 212 storres
                ccReducedPolynomialsList.append(ccReducedPolynomial)
1110 212 storres
        else:
1111 212 storres
            #print l2Norm.n() , ">", nAtAlpha
1112 212 storres
            pass
1113 229 storres
    if debug:
1114 229 storres
        print ccVectorsCount, "out of ", len(ccReducedPolynomialsList),
1115 229 storres
        print "took Coppersmith text."
1116 212 storres
    if len(ccReducedPolynomialsList) < 2:
1117 212 storres
        print "Less than 2 Coppersmith condition compliant vectors."
1118 212 storres
        return ()
1119 229 storres
    if debug:
1120 229 storres
        print "Reduced and Coppersmith compliant polynomials list", ccReducedPolynomialsList
1121 212 storres
    return ccReducedPolynomialsList
1122 212 storres
# End slz_compute_coppersmith_reduced_polynomials_with_lattice volume
1123 212 storres
1124 219 storres
def slz_compute_initial_lattice_matrix(inputPolynomial,
1125 219 storres
                                       alpha,
1126 219 storres
                                       N,
1127 219 storres
                                       iBound,
1128 228 storres
                                       tBound,
1129 228 storres
                                       debug = False):
1130 219 storres
    """
1131 219 storres
    For a given set of arguments (see below), compute the initial lattice
1132 219 storres
    that could be reduced.
1133 219 storres
    INPUT:
1134 219 storres
1135 219 storres
    - "inputPolynomial" -- (no default) a bivariate integer polynomial;
1136 219 storres
    - "alpha" -- the alpha parameter of the Coppersmith algorithm;
1137 219 storres
    - "N" -- the modulus;
1138 219 storres
    - "iBound" -- the bound on the first variable;
1139 219 storres
    - "tBound" -- the bound on the second variable.
1140 219 storres
1141 219 storres
    OUTPUT:
1142 219 storres
1143 219 storres
    A list of bivariate integer polynomial obtained using the Coppersmith
1144 219 storres
    algorithm. The polynomials correspond to the rows of the LLL-reduce
1145 219 storres
    reduced base that comply with the Coppersmith condition.
1146 219 storres
    """
1147 219 storres
    # Arguments check.
1148 219 storres
    if iBound == 0 or tBound == 0:
1149 219 storres
        return None
1150 219 storres
    # End arguments check.
1151 219 storres
    nAtAlpha = N^alpha
1152 219 storres
    ## Building polynomials for matrix.
1153 219 storres
    polyRing   = inputPolynomial.parent()
1154 219 storres
    # Whatever the 2 variables are actually called, we call them
1155 219 storres
    # 'i' and 't' in all the variable names.
1156 219 storres
    (iVariable, tVariable) = inputPolynomial.variables()[:2]
1157 219 storres
    #print polyVars[0], type(polyVars[0])
1158 219 storres
    initialPolynomial = inputPolynomial.subs({iVariable:iVariable * iBound,
1159 219 storres
                                              tVariable:tVariable * tBound})
1160 219 storres
    polynomialsList = \
1161 219 storres
        spo_polynomial_to_polynomials_list_8(initialPolynomial,
1162 219 storres
                                             alpha,
1163 219 storres
                                             N,
1164 219 storres
                                             iBound,
1165 219 storres
                                             tBound,
1166 219 storres
                                             0)
1167 219 storres
    #print "Polynomials list:", polynomialsList
1168 219 storres
    ## Building the proto matrix.
1169 219 storres
    knownMonomials = []
1170 219 storres
    protoMatrix    = []
1171 219 storres
    for poly in polynomialsList:
1172 219 storres
        spo_add_polynomial_coeffs_to_matrix_row(poly,
1173 219 storres
                                                knownMonomials,
1174 219 storres
                                                protoMatrix,
1175 219 storres
                                                0)
1176 219 storres
    matrixToReduce = spo_proto_to_row_matrix(protoMatrix)
1177 228 storres
    if debug:
1178 228 storres
        print "Initial basis polynomials"
1179 228 storres
        for poly in polynomialsList:
1180 228 storres
            print poly
1181 219 storres
    return matrixToReduce
1182 219 storres
# End slz_compute_initial_lattice_matrix.
1183 219 storres
1184 122 storres
def slz_compute_integer_polynomial_modular_roots(inputPolynomial,
1185 122 storres
                                                 alpha,
1186 122 storres
                                                 N,
1187 122 storres
                                                 iBound,
1188 122 storres
                                                 tBound):
1189 122 storres
    """
1190 123 storres
    For a given set of arguments (see below), compute the polynomial modular
1191 122 storres
    roots, if any.
1192 124 storres
1193 122 storres
    """
1194 123 storres
    # Arguments check.
1195 123 storres
    if iBound == 0 or tBound == 0:
1196 123 storres
        return set()
1197 123 storres
    # End arguments check.
1198 122 storres
    nAtAlpha = N^alpha
1199 122 storres
    ## Building polynomials for matrix.
1200 122 storres
    polyRing   = inputPolynomial.parent()
1201 122 storres
    # Whatever the 2 variables are actually called, we call them
1202 122 storres
    # 'i' and 't' in all the variable names.
1203 122 storres
    (iVariable, tVariable) = inputPolynomial.variables()[:2]
1204 125 storres
    ccReducedPolynomialsList = \
1205 125 storres
        slz_compute_coppersmith_reduced_polynomials (inputPolynomial,
1206 125 storres
                                                     alpha,
1207 125 storres
                                                     N,
1208 125 storres
                                                     iBound,
1209 125 storres
                                                     tBound)
1210 125 storres
    if len(ccReducedPolynomialsList) == 0:
1211 125 storres
        return set()
1212 122 storres
    ## Create the valid (poly1 and poly2 are algebraically independent)
1213 122 storres
    # resultant tuples (poly1, poly2, resultant(poly1, poly2)).
1214 122 storres
    # Try to mix and match all the polynomial pairs built from the
1215 122 storres
    # ccReducedPolynomialsList to obtain non zero resultants.
1216 122 storres
    resultantsInITuplesList = []
1217 122 storres
    for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList)-1):
1218 122 storres
        for polyInnerIndex in xrange(polyOuterIndex+1,
1219 122 storres
                                     len(ccReducedPolynomialsList)):
1220 122 storres
            # Compute the resultant in resultants in the
1221 122 storres
            # first variable (is it the optimal choice?).
1222 122 storres
            resultantInI = \
1223 122 storres
               ccReducedPolynomialsList[polyOuterIndex].resultant(ccReducedPolynomialsList[polyInnerIndex],
1224 122 storres
                                                                  ccReducedPolynomialsList[0].parent(str(iVariable)))
1225 122 storres
            #print "Resultant", resultantInI
1226 122 storres
            # Test algebraic independence.
1227 122 storres
            if not resultantInI.is_zero():
1228 122 storres
                resultantsInITuplesList.append((ccReducedPolynomialsList[polyOuterIndex],
1229 122 storres
                                                 ccReducedPolynomialsList[polyInnerIndex],
1230 122 storres
                                                 resultantInI))
1231 122 storres
    # If no non zero resultant was found: we can't get no algebraically
1232 122 storres
    # independent polynomials pair. Give up!
1233 122 storres
    if len(resultantsInITuplesList) == 0:
1234 123 storres
        return set()
1235 123 storres
    #print resultantsInITuplesList
1236 122 storres
    # Compute the roots.
1237 122 storres
    Zi = ZZ[str(iVariable)]
1238 122 storres
    Zt = ZZ[str(tVariable)]
1239 122 storres
    polynomialRootsSet = set()
1240 122 storres
    # First, solve in the second variable since resultants are in the first
1241 122 storres
    # variable.
1242 122 storres
    for resultantInITuple in resultantsInITuplesList:
1243 122 storres
        tRootsList = Zt(resultantInITuple[2]).roots()
1244 122 storres
        # For each tRoot, compute the corresponding iRoots and check
1245 123 storres
        # them in the input polynomial.
1246 122 storres
        for tRoot in tRootsList:
1247 123 storres
            #print "tRoot:", tRoot
1248 122 storres
            # Roots returned by root() are (value, multiplicity) tuples.
1249 122 storres
            iRootsList = \
1250 122 storres
                Zi(resultantInITuple[0].subs({resultantInITuple[0].variables()[1]:tRoot[0]})).roots()
1251 123 storres
            print iRootsList
1252 122 storres
            # The iRootsList can be empty, hence the test.
1253 122 storres
            if len(iRootsList) != 0:
1254 122 storres
                for iRoot in iRootsList:
1255 122 storres
                    polyEvalModN = inputPolynomial(iRoot[0], tRoot[0]) / N
1256 122 storres
                    # polyEvalModN must be an integer.
1257 122 storres
                    if polyEvalModN == int(polyEvalModN):
1258 122 storres
                        polynomialRootsSet.add((iRoot[0],tRoot[0]))
1259 122 storres
    return polynomialRootsSet
1260 122 storres
# End slz_compute_integer_polynomial_modular_roots.
1261 122 storres
#
1262 125 storres
def slz_compute_integer_polynomial_modular_roots_2(inputPolynomial,
1263 125 storres
                                                 alpha,
1264 125 storres
                                                 N,
1265 125 storres
                                                 iBound,
1266 125 storres
                                                 tBound):
1267 125 storres
    """
1268 125 storres
    For a given set of arguments (see below), compute the polynomial modular
1269 125 storres
    roots, if any.
1270 125 storres
    This version differs in the way resultants are computed.
1271 125 storres
    """
1272 125 storres
    # Arguments check.
1273 125 storres
    if iBound == 0 or tBound == 0:
1274 125 storres
        return set()
1275 125 storres
    # End arguments check.
1276 125 storres
    nAtAlpha = N^alpha
1277 125 storres
    ## Building polynomials for matrix.
1278 125 storres
    polyRing   = inputPolynomial.parent()
1279 125 storres
    # Whatever the 2 variables are actually called, we call them
1280 125 storres
    # 'i' and 't' in all the variable names.
1281 125 storres
    (iVariable, tVariable) = inputPolynomial.variables()[:2]
1282 125 storres
    #print polyVars[0], type(polyVars[0])
1283 125 storres
    ccReducedPolynomialsList = \
1284 125 storres
        slz_compute_coppersmith_reduced_polynomials (inputPolynomial,
1285 125 storres
                                                     alpha,
1286 125 storres
                                                     N,
1287 125 storres
                                                     iBound,
1288 125 storres
                                                     tBound)
1289 125 storres
    if len(ccReducedPolynomialsList) == 0:
1290 125 storres
        return set()
1291 125 storres
    ## Create the valid (poly1 and poly2 are algebraically independent)
1292 125 storres
    # resultant tuples (poly1, poly2, resultant(poly1, poly2)).
1293 125 storres
    # Try to mix and match all the polynomial pairs built from the
1294 125 storres
    # ccReducedPolynomialsList to obtain non zero resultants.
1295 125 storres
    resultantsInTTuplesList = []
1296 125 storres
    for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList)-1):
1297 125 storres
        for polyInnerIndex in xrange(polyOuterIndex+1,
1298 125 storres
                                     len(ccReducedPolynomialsList)):
1299 125 storres
            # Compute the resultant in resultants in the
1300 125 storres
            # first variable (is it the optimal choice?).
1301 125 storres
            resultantInT = \
1302 125 storres
               ccReducedPolynomialsList[polyOuterIndex].resultant(ccReducedPolynomialsList[polyInnerIndex],
1303 125 storres
                                                                  ccReducedPolynomialsList[0].parent(str(tVariable)))
1304 125 storres
            #print "Resultant", resultantInT
1305 125 storres
            # Test algebraic independence.
1306 125 storres
            if not resultantInT.is_zero():
1307 125 storres
                resultantsInTTuplesList.append((ccReducedPolynomialsList[polyOuterIndex],
1308 125 storres
                                                 ccReducedPolynomialsList[polyInnerIndex],
1309 125 storres
                                                 resultantInT))
1310 125 storres
    # If no non zero resultant was found: we can't get no algebraically
1311 125 storres
    # independent polynomials pair. Give up!
1312 125 storres
    if len(resultantsInTTuplesList) == 0:
1313 125 storres
        return set()
1314 125 storres
    #print resultantsInITuplesList
1315 125 storres
    # Compute the roots.
1316 125 storres
    Zi = ZZ[str(iVariable)]
1317 125 storres
    Zt = ZZ[str(tVariable)]
1318 125 storres
    polynomialRootsSet = set()
1319 125 storres
    # First, solve in the second variable since resultants are in the first
1320 125 storres
    # variable.
1321 125 storres
    for resultantInTTuple in resultantsInTTuplesList:
1322 125 storres
        iRootsList = Zi(resultantInTTuple[2]).roots()
1323 125 storres
        # For each iRoot, compute the corresponding tRoots and check
1324 125 storres
        # them in the input polynomial.
1325 125 storres
        for iRoot in iRootsList:
1326 125 storres
            #print "iRoot:", iRoot
1327 125 storres
            # Roots returned by root() are (value, multiplicity) tuples.
1328 125 storres
            tRootsList = \
1329 125 storres
                Zt(resultantInTTuple[0].subs({resultantInTTuple[0].variables()[0]:iRoot[0]})).roots()
1330 125 storres
            print tRootsList
1331 125 storres
            # The tRootsList can be empty, hence the test.
1332 125 storres
            if len(tRootsList) != 0:
1333 125 storres
                for tRoot in tRootsList:
1334 125 storres
                    polyEvalModN = inputPolynomial(iRoot[0],tRoot[0]) / N
1335 125 storres
                    # polyEvalModN must be an integer.
1336 125 storres
                    if polyEvalModN == int(polyEvalModN):
1337 125 storres
                        polynomialRootsSet.add((iRoot[0],tRoot[0]))
1338 125 storres
    return polynomialRootsSet
1339 125 storres
# End slz_compute_integer_polynomial_modular_roots_2.
1340 125 storres
#
1341 61 storres
def slz_compute_polynomial_and_interval(functionSo, degreeSo, lowerBoundSa,
1342 218 storres
                                        upperBoundSa, approxAccurSa,
1343 272 storres
                                        precSa=None, debug=False):
1344 61 storres
    """
1345 61 storres
    Under the assumptions listed for slz_get_intervals_and_polynomials, compute
1346 61 storres
    a polynomial that approximates the function on a an interval starting
1347 61 storres
    at lowerBoundSa and finishing at a value that guarantees that the polynomial
1348 61 storres
    approximates with the expected precision.
1349 61 storres
    The interval upper bound is lowered until the expected approximation
1350 61 storres
    precision is reached.
1351 61 storres
    The polynomial, the bounds, the center of the interval and the error
1352 61 storres
    are returned.
1353 272 storres
    Argument debug is not used.
1354 156 storres
    OUTPUT:
1355 124 storres
    A tuple made of 4 Sollya objects:
1356 124 storres
    - a polynomial;
1357 124 storres
    - an range (an interval, not in the sense of number given as an interval);
1358 124 storres
    - the center of the interval;
1359 124 storres
    - the maximum error in the approximation of the input functionSo by the
1360 218 storres
      output polynomial ; this error <= approxAccurSaS.
1361 124 storres
1362 61 storres
    """
1363 218 storres
    #print"In slz_compute_polynomial_and_interval..."
1364 166 storres
    ## Superficial argument check.
1365 166 storres
    if lowerBoundSa > upperBoundSa:
1366 166 storres
        return None
1367 218 storres
    ## Change Sollya precision, if requested.
1368 218 storres
    if precSa is None:
1369 218 storres
        precSa = ceil((RR('1.5') * abs(RR(approxAccurSa).log2())) / 64) * 64
1370 218 storres
        #print "Computed internal precision:", precSa
1371 218 storres
        if precSa < 192:
1372 218 storres
            precSa = 192
1373 226 storres
    sollyaPrecChanged = False
1374 226 storres
    (initialSollyaPrecSo, initialSollyaPrecSa) = pobyso_get_prec_so_so_sa()
1375 226 storres
    if precSa > initialSollyaPrecSa:
1376 226 storres
        if precSa <= 2:
1377 226 storres
            print inspect.stack()[0][3], ": precision change <=2 requested."
1378 226 storres
        pobyso_set_prec_sa_so(precSa)
1379 218 storres
        sollyaPrecChanged = True
1380 61 storres
    RRR = lowerBoundSa.parent()
1381 176 storres
    intervalShrinkConstFactorSa = RRR('0.9')
1382 61 storres
    absoluteErrorTypeSo = pobyso_absolute_so_so()
1383 61 storres
    currentRangeSo = pobyso_bounds_to_range_sa_so(lowerBoundSa, upperBoundSa)
1384 61 storres
    currentUpperBoundSa = upperBoundSa
1385 61 storres
    currentLowerBoundSa = lowerBoundSa
1386 61 storres
    # What we want here is the polynomial without the variable change,
1387 61 storres
    # since our actual variable will be x-intervalCenter defined over the
1388 61 storres
    # domain [lowerBound-intervalCenter , upperBound-intervalCenter].
1389 61 storres
    (polySo, intervalCenterSo, maxErrorSo) = \
1390 61 storres
        pobyso_taylor_expansion_no_change_var_so_so(functionSo, degreeSo,
1391 61 storres
                                                    currentRangeSo,
1392 61 storres
                                                    absoluteErrorTypeSo)
1393 61 storres
    maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
1394 218 storres
    while maxErrorSa > approxAccurSa:
1395 181 storres
        print "++Approximation error:", maxErrorSa.n()
1396 81 storres
        sollya_lib_clear_obj(polySo)
1397 81 storres
        sollya_lib_clear_obj(intervalCenterSo)
1398 120 storres
        sollya_lib_clear_obj(maxErrorSo)
1399 181 storres
        # Very empirical shrinking factor.
1400 218 storres
        shrinkFactorSa = 1 /  (maxErrorSa/approxAccurSa).log2().abs()
1401 181 storres
        print "Shrink factor:", \
1402 181 storres
              shrinkFactorSa.n(), \
1403 181 storres
              intervalShrinkConstFactorSa
1404 182 storres
        print
1405 218 storres
        #errorRatioSa = approxAccurSa/maxErrorSa
1406 61 storres
        #print "Error ratio: ", errorRatioSa
1407 181 storres
        # Make sure interval shrinks.
1408 81 storres
        if shrinkFactorSa > intervalShrinkConstFactorSa:
1409 81 storres
            actualShrinkFactorSa = intervalShrinkConstFactorSa
1410 81 storres
            #print "Fixed"
1411 61 storres
        else:
1412 81 storres
            actualShrinkFactorSa = shrinkFactorSa
1413 81 storres
            #print "Computed",shrinkFactorSa,maxErrorSa
1414 81 storres
            #print shrinkFactorSa, maxErrorSa
1415 101 storres
        #print "Shrink factor", actualShrinkFactorSa
1416 81 storres
        currentUpperBoundSa = currentLowerBoundSa + \
1417 181 storres
                                (currentUpperBoundSa - currentLowerBoundSa) * \
1418 181 storres
                                actualShrinkFactorSa
1419 71 storres
        #print "Current upper bound:", currentUpperBoundSa
1420 61 storres
        sollya_lib_clear_obj(currentRangeSo)
1421 181 storres
        # Check what is left with the bounds.
1422 101 storres
        if currentUpperBoundSa <= currentLowerBoundSa or \
1423 101 storres
              currentUpperBoundSa == currentLowerBoundSa.nextabove():
1424 86 storres
            sollya_lib_clear_obj(absoluteErrorTypeSo)
1425 86 storres
            print "Can't find an interval."
1426 86 storres
            print "Use either or both a higher polynomial degree or a higher",
1427 86 storres
            print "internal precision."
1428 86 storres
            print "Aborting!"
1429 218 storres
            if sollyaPrecChanged:
1430 226 storres
                pobyso_set_prec_so_so(initialSollyaPrecSo)
1431 226 storres
            sollya_lib_clear_obj(initialSollyaPrecSo)
1432 218 storres
            return None
1433 61 storres
        currentRangeSo = pobyso_bounds_to_range_sa_so(currentLowerBoundSa,
1434 61 storres
                                                      currentUpperBoundSa)
1435 86 storres
        # print "New interval:",
1436 86 storres
        # pobyso_autoprint(currentRangeSo)
1437 120 storres
        #print "Second Taylor expansion call."
1438 61 storres
        (polySo, intervalCenterSo, maxErrorSo) = \
1439 61 storres
            pobyso_taylor_expansion_no_change_var_so_so(functionSo, degreeSo,
1440 61 storres
                                                        currentRangeSo,
1441 61 storres
                                                        absoluteErrorTypeSo)
1442 61 storres
        #maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo, RRR)
1443 85 storres
        #print "Max errorSo:",
1444 85 storres
        #pobyso_autoprint(maxErrorSo)
1445 61 storres
        maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
1446 85 storres
        #print "Max errorSa:", maxErrorSa
1447 85 storres
        #print "Sollya prec:",
1448 85 storres
        #pobyso_autoprint(sollya_lib_get_prec(None))
1449 218 storres
    # End while
1450 61 storres
    sollya_lib_clear_obj(absoluteErrorTypeSo)
1451 218 storres
    if sollyaPrecChanged:
1452 226 storres
        pobyso_set_prec_so_so(initialSollyaPrecSo)
1453 226 storres
    sollya_lib_clear_obj(initialSollyaPrecSo)
1454 176 storres
    return (polySo, currentRangeSo, intervalCenterSo, maxErrorSo)
1455 81 storres
# End slz_compute_polynomial_and_interval
1456 218 storres
1457 218 storres
def slz_compute_polynomial_and_interval_01(functionSo, degreeSo, lowerBoundSa,
1458 218 storres
                                        upperBoundSa, approxAccurSa,
1459 219 storres
                                        sollyaPrecSa=None, debug=False):
1460 219 storres
    """
1461 219 storres
    Under the assumptions listed for slz_get_intervals_and_polynomials, compute
1462 219 storres
    a polynomial that approximates the function on a an interval starting
1463 219 storres
    at lowerBoundSa and finishing at a value that guarantees that the polynomial
1464 219 storres
    approximates with the expected precision.
1465 219 storres
    The interval upper bound is lowered until the expected approximation
1466 219 storres
    precision is reached.
1467 219 storres
    The polynomial, the bounds, the center of the interval and the error
1468 219 storres
    are returned.
1469 219 storres
    OUTPUT:
1470 219 storres
    A tuple made of 4 Sollya objects:
1471 219 storres
    - a polynomial;
1472 219 storres
    - an range (an interval, not in the sense of number given as an interval);
1473 219 storres
    - the center of the interval;
1474 219 storres
    - the maximum error in the approximation of the input functionSo by the
1475 219 storres
      output polynomial ; this error <= approxAccurSaS.
1476 272 storres
1477 272 storres
    Changes from version 0 (no number):
1478 272 storres
    - make use of debug argument;
1479 272 storres
    - polynomial coefficients are "shaved".
1480 219 storres
1481 219 storres
    """
1482 219 storres
    #print"In slz_compute_polynomial_and_interval..."
1483 219 storres
    ## Superficial argument check.
1484 219 storres
    if lowerBoundSa > upperBoundSa:
1485 225 storres
        print inspect.stack()[0][3], ": lower bound is larger than upper bound. "
1486 219 storres
        return None
1487 219 storres
    ## Change Sollya precision, if requested.
1488 226 storres
    (initialSollyaPrecSo, initialSollyaPrecSa) = pobyso_get_prec_so_so_sa()
1489 225 storres
    sollyaPrecChangedSa = False
1490 225 storres
    if sollyaPrecSa is None:
1491 226 storres
        sollyaPrecSa = initialSollyaPrecSa
1492 219 storres
    else:
1493 226 storres
        if sollyaPrecSa > initialSollyaPrecSa:
1494 226 storres
            if sollyaPrecSa <= 2:
1495 226 storres
                print inspect.stack()[0][3], ": precision change <= 2 requested."
1496 225 storres
            pobyso_set_prec_sa_so(sollyaPrecSa)
1497 225 storres
            sollyaPrecChangedSa = True
1498 225 storres
    ## Other initializations and data recovery.
1499 219 storres
    RRR = lowerBoundSa.parent()
1500 219 storres
    intervalShrinkConstFactorSa = RRR('0.9')
1501 219 storres
    absoluteErrorTypeSo = pobyso_absolute_so_so()
1502 219 storres
    currentRangeSo = pobyso_bounds_to_range_sa_so(lowerBoundSa, upperBoundSa)
1503 219 storres
    currentUpperBoundSa = upperBoundSa
1504 219 storres
    currentLowerBoundSa = lowerBoundSa
1505 219 storres
    # What we want here is the polynomial without the variable change,
1506 219 storres
    # since our actual variable will be x-intervalCenter defined over the
1507 219 storres
    # domain [lowerBound-intervalCenter , upperBound-intervalCenter].
1508 219 storres
    (polySo, intervalCenterSo, maxErrorSo) = \
1509 219 storres
        pobyso_taylor_expansion_no_change_var_so_so(functionSo, degreeSo,
1510 219 storres
                                                    currentRangeSo,
1511 219 storres
                                                    absoluteErrorTypeSo)
1512 219 storres
    maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
1513 278 storres
    ## Expression "approxAccurSa/2" (instead of just approxAccurSa) is added
1514 278 storres
    #  since we use polynomial shaving. In order for it to work, we must start
1515 278 storres
    #  with a better accuracy.
1516 278 storres
    while maxErrorSa > approxAccurSa/2:
1517 219 storres
        print "++Approximation error:", maxErrorSa.n()
1518 219 storres
        sollya_lib_clear_obj(polySo)
1519 219 storres
        sollya_lib_clear_obj(intervalCenterSo)
1520 219 storres
        sollya_lib_clear_obj(maxErrorSo)
1521 219 storres
        # Very empirical shrinking factor.
1522 219 storres
        shrinkFactorSa = 1 /  (maxErrorSa/approxAccurSa).log2().abs()
1523 219 storres
        print "Shrink factor:", \
1524 219 storres
              shrinkFactorSa.n(), \
1525 219 storres
              intervalShrinkConstFactorSa
1526 219 storres
        print
1527 219 storres
        #errorRatioSa = approxAccurSa/maxErrorSa
1528 219 storres
        #print "Error ratio: ", errorRatioSa
1529 219 storres
        # Make sure interval shrinks.
1530 219 storres
        if shrinkFactorSa > intervalShrinkConstFactorSa:
1531 219 storres
            actualShrinkFactorSa = intervalShrinkConstFactorSa
1532 219 storres
            #print "Fixed"
1533 219 storres
        else:
1534 219 storres
            actualShrinkFactorSa = shrinkFactorSa
1535 219 storres
            #print "Computed",shrinkFactorSa,maxErrorSa
1536 219 storres
            #print shrinkFactorSa, maxErrorSa
1537 219 storres
        #print "Shrink factor", actualShrinkFactorSa
1538 219 storres
        currentUpperBoundSa = currentLowerBoundSa + \
1539 219 storres
                                (currentUpperBoundSa - currentLowerBoundSa) * \
1540 219 storres
                                actualShrinkFactorSa
1541 219 storres
        #print "Current upper bound:", currentUpperBoundSa
1542 219 storres
        sollya_lib_clear_obj(currentRangeSo)
1543 219 storres
        # Check what is left with the bounds.
1544 219 storres
        if currentUpperBoundSa <= currentLowerBoundSa or \
1545 219 storres
              currentUpperBoundSa == currentLowerBoundSa.nextabove():
1546 219 storres
            sollya_lib_clear_obj(absoluteErrorTypeSo)
1547 219 storres
            print "Can't find an interval."
1548 219 storres
            print "Use either or both a higher polynomial degree or a higher",
1549 219 storres
            print "internal precision."
1550 219 storres
            print "Aborting!"
1551 225 storres
            if sollyaPrecChangedSa:
1552 225 storres
                pobyso_set_prec_so_so(initialSollyaPrecSo)
1553 226 storres
            sollya_lib_clear_obj(initialSollyaPrecSo)
1554 219 storres
            return None
1555 219 storres
        currentRangeSo = pobyso_bounds_to_range_sa_so(currentLowerBoundSa,
1556 219 storres
                                                      currentUpperBoundSa)
1557 219 storres
        # print "New interval:",
1558 219 storres
        # pobyso_autoprint(currentRangeSo)
1559 219 storres
        #print "Second Taylor expansion call."
1560 219 storres
        (polySo, intervalCenterSo, maxErrorSo) = \
1561 219 storres
            pobyso_taylor_expansion_no_change_var_so_so(functionSo, degreeSo,
1562 219 storres
                                                        currentRangeSo,
1563 219 storres
                                                        absoluteErrorTypeSo)
1564 219 storres
        #maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo, RRR)
1565 219 storres
        #print "Max errorSo:",
1566 219 storres
        #pobyso_autoprint(maxErrorSo)
1567 219 storres
        maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
1568 219 storres
        #print "Max errorSa:", maxErrorSa
1569 219 storres
        #print "Sollya prec:",
1570 219 storres
        #pobyso_autoprint(sollya_lib_get_prec(None))
1571 219 storres
    # End while
1572 219 storres
    sollya_lib_clear_obj(absoluteErrorTypeSo)
1573 219 storres
    itpSo           = pobyso_constant_from_int_sa_so(floor(sollyaPrecSa/3))
1574 219 storres
    ftpSo           = pobyso_constant_from_int_sa_so(floor(2*sollyaPrecSa/3))
1575 219 storres
    maxPrecSo       = pobyso_constant_from_int_sa_so(sollyaPrecSa)
1576 219 storres
    approxAccurSo   = pobyso_constant_sa_so(RR(approxAccurSa))
1577 219 storres
    if debug:
1578 229 storres
        print inspect.stack()[0][3], "SollyaPrecSa:", sollyaPrecSa
1579 219 storres
        print "About to call polynomial rounding with:"
1580 219 storres
        print "polySo: ",           ; pobyso_autoprint(polySo)
1581 219 storres
        print "functionSo: ",       ; pobyso_autoprint(functionSo)
1582 219 storres
        print "intervalCenterSo: ", ; pobyso_autoprint(intervalCenterSo)
1583 219 storres
        print "currentRangeSo: ",   ; pobyso_autoprint(currentRangeSo)
1584 219 storres
        print "itpSo: ",            ; pobyso_autoprint(itpSo)
1585 219 storres
        print "ftpSo: ",            ; pobyso_autoprint(ftpSo)
1586 219 storres
        print "maxPrecSo: ",        ; pobyso_autoprint(maxPrecSo)
1587 219 storres
        print "approxAccurSo: ",    ; pobyso_autoprint(approxAccurSo)
1588 224 storres
    """
1589 224 storres
    # Naive rounding.
1590 219 storres
    (roundedPolySo, roundedPolyMaxErrSo) = \
1591 219 storres
    pobyso_polynomial_coefficients_progressive_round_so_so(polySo,
1592 219 storres
                                                           functionSo,
1593 219 storres
                                                           intervalCenterSo,
1594 219 storres
                                                           currentRangeSo,
1595 219 storres
                                                           itpSo,
1596 219 storres
                                                           ftpSo,
1597 219 storres
                                                           maxPrecSo,
1598 219 storres
                                                           approxAccurSo)
1599 224 storres
    """
1600 224 storres
    # Proved rounding.
1601 224 storres
    (roundedPolySo, roundedPolyMaxErrSo) = \
1602 224 storres
        pobyso_round_coefficients_progressive_so_so(polySo,
1603 224 storres
                                                    functionSo,
1604 224 storres
                                                    maxPrecSo,
1605 224 storres
                                                    currentRangeSo,
1606 224 storres
                                                    intervalCenterSo,
1607 224 storres
                                                    maxErrorSo,
1608 224 storres
                                                    approxAccurSo,
1609 224 storres
                                                    debug=False)
1610 224 storres
    #### Comment out the two next lines when polynomial rounding is activated.
1611 224 storres
    #roundedPolySo = sollya_lib_copy_obj(polySo)
1612 224 storres
    #roundedPolyMaxErrSo =  sollya_lib_copy_obj(maxErrorSo)
1613 219 storres
    sollya_lib_clear_obj(polySo)
1614 219 storres
    sollya_lib_clear_obj(maxErrorSo)
1615 219 storres
    sollya_lib_clear_obj(itpSo)
1616 219 storres
    sollya_lib_clear_obj(ftpSo)
1617 219 storres
    sollya_lib_clear_obj(approxAccurSo)
1618 225 storres
    if sollyaPrecChangedSa:
1619 230 storres
        pobyso_set_prec_so_so(initialSollyaPrecSo)
1620 230 storres
    sollya_lib_clear_obj(initialSollyaPrecSo)
1621 219 storres
    if debug:
1622 219 storres
        print "1: ", ; pobyso_autoprint(roundedPolySo)
1623 219 storres
        print "2: ", ; pobyso_autoprint(currentRangeSo)
1624 219 storres
        print "3: ", ; pobyso_autoprint(intervalCenterSo)
1625 219 storres
        print "4: ", ; pobyso_autoprint(roundedPolyMaxErrSo)
1626 219 storres
    return (roundedPolySo, currentRangeSo, intervalCenterSo, roundedPolyMaxErrSo)
1627 219 storres
# End slz_compute_polynomial_and_interval_01
1628 219 storres
1629 219 storres
def slz_compute_polynomial_and_interval_02(functionSo, degreeSo, lowerBoundSa,
1630 219 storres
                                        upperBoundSa, approxAccurSa,
1631 227 storres
                                        sollyaPrecSa=None, debug=True ):
1632 218 storres
    """
1633 218 storres
    Under the assumptions listed for slz_get_intervals_and_polynomials, compute
1634 218 storres
    a polynomial that approximates the function on a an interval starting
1635 218 storres
    at lowerBoundSa and finishing at a value that guarantees that the polynomial
1636 218 storres
    approximates with the expected precision.
1637 218 storres
    The interval upper bound is lowered until the expected approximation
1638 218 storres
    precision is reached.
1639 218 storres
    The polynomial, the bounds, the center of the interval and the error
1640 218 storres
    are returned.
1641 218 storres
    OUTPUT:
1642 218 storres
    A tuple made of 4 Sollya objects:
1643 218 storres
    - a polynomial;
1644 218 storres
    - an range (an interval, not in the sense of number given as an interval);
1645 218 storres
    - the center of the interval;
1646 218 storres
    - the maximum error in the approximation of the input functionSo by the
1647 218 storres
      output polynomial ; this error <= approxAccurSaS.
1648 278 storres
1649 228 storres
    Changes fom v 01:
1650 227 storres
        extra verbose.
1651 218 storres
    """
1652 218 storres
    print"In slz_compute_polynomial_and_interval..."
1653 218 storres
    ## Superficial argument check.
1654 218 storres
    if lowerBoundSa > upperBoundSa:
1655 218 storres
        return None
1656 218 storres
    ## Change Sollya precision, if requested.
1657 226 storres
    sollyaPrecChanged = False
1658 226 storres
    (initialSollyaPrecSo, initialSollyaPrecSa) = pobyso_get_prec_so_so_sa()
1659 227 storres
    #print "Initial Sollya prec:", initialSollyaPrecSa, type(initialSollyaPrecSa)
1660 227 storres
    if sollyaPrecSa is None:
1661 226 storres
        sollyaPrecSa = initialSollyaPrecSa
1662 226 storres
    else:
1663 226 storres
        if sollyaPrecSa <= 2:
1664 226 storres
            print inspect.stack()[0][3], ": precision change <=2 requested."
1665 218 storres
        pobyso_set_prec_sa_so(sollyaPrecSa)
1666 226 storres
        sollyaPrecChanged = True
1667 218 storres
    RRR = lowerBoundSa.parent()
1668 218 storres
    intervalShrinkConstFactorSa = RRR('0.9')
1669 218 storres
    absoluteErrorTypeSo = pobyso_absolute_so_so()
1670 218 storres
    currentRangeSo = pobyso_bounds_to_range_sa_so(lowerBoundSa, upperBoundSa)
1671 218 storres
    currentUpperBoundSa = upperBoundSa
1672 218 storres
    currentLowerBoundSa = lowerBoundSa
1673 227 storres
    #pobyso_autoprint(functionSo)
1674 227 storres
    #pobyso_autoprint(degreeSo)
1675 227 storres
    #pobyso_autoprint(currentRangeSo)
1676 227 storres
    #pobyso_autoprint(absoluteErrorTypeSo)
1677 227 storres
    ## What we want here is the polynomial without the variable change,
1678 227 storres
    #  since our actual variable will be x-intervalCenter defined over the
1679 227 storres
    #  domain [lowerBound-intervalCenter , upperBound-intervalCenter].
1680 218 storres
    (polySo, intervalCenterSo, maxErrorSo) = \
1681 218 storres
        pobyso_taylor_expansion_no_change_var_so_so(functionSo, degreeSo,
1682 218 storres
                                                    currentRangeSo,
1683 218 storres
                                                    absoluteErrorTypeSo)
1684 218 storres
    maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
1685 227 storres
    print "...after Taylor expansion."
1686 278 storres
    ## Expression "approxAccurSa/2" (instead of just approxAccurSa) is added
1687 278 storres
    #  since we use polynomial shaving. In order for it to work, we must start
1688 278 storres
    #  with a better accuracy.
1689 278 storres
    while maxErrorSa > approxAccurSa/2:
1690 218 storres
        print "++Approximation error:", maxErrorSa.n()
1691 218 storres
        sollya_lib_clear_obj(polySo)
1692 218 storres
        sollya_lib_clear_obj(intervalCenterSo)
1693 218 storres
        sollya_lib_clear_obj(maxErrorSo)
1694 218 storres
        # Very empirical shrinking factor.
1695 218 storres
        shrinkFactorSa = 1 /  (maxErrorSa/approxAccurSa).log2().abs()
1696 218 storres
        print "Shrink factor:", \
1697 218 storres
              shrinkFactorSa.n(), \
1698 218 storres
              intervalShrinkConstFactorSa
1699 218 storres
        print
1700 218 storres
        #errorRatioSa = approxAccurSa/maxErrorSa
1701 218 storres
        #print "Error ratio: ", errorRatioSa
1702 218 storres
        # Make sure interval shrinks.
1703 218 storres
        if shrinkFactorSa > intervalShrinkConstFactorSa:
1704 218 storres
            actualShrinkFactorSa = intervalShrinkConstFactorSa
1705 218 storres
            #print "Fixed"
1706 218 storres
        else:
1707 218 storres
            actualShrinkFactorSa = shrinkFactorSa
1708 218 storres
            #print "Computed",shrinkFactorSa,maxErrorSa
1709 218 storres
            #print shrinkFactorSa, maxErrorSa
1710 218 storres
        #print "Shrink factor", actualShrinkFactorSa
1711 218 storres
        currentUpperBoundSa = currentLowerBoundSa + \
1712 218 storres
                                (currentUpperBoundSa - currentLowerBoundSa) * \
1713 218 storres
                                actualShrinkFactorSa
1714 218 storres
        #print "Current upper bound:", currentUpperBoundSa
1715 218 storres
        sollya_lib_clear_obj(currentRangeSo)
1716 218 storres
        # Check what is left with the bounds.
1717 218 storres
        if currentUpperBoundSa <= currentLowerBoundSa or \
1718 218 storres
              currentUpperBoundSa == currentLowerBoundSa.nextabove():
1719 218 storres
            sollya_lib_clear_obj(absoluteErrorTypeSo)
1720 218 storres
            print "Can't find an interval."
1721 218 storres
            print "Use either or both a higher polynomial degree or a higher",
1722 218 storres
            print "internal precision."
1723 218 storres
            print "Aborting!"
1724 226 storres
            if sollyaPrecChanged:
1725 226 storres
                pobyso_set_prec_so_so(initialSollyaPrecSo)
1726 226 storres
            sollya_lib_clear_obj(initialSollyaPrecSo)
1727 218 storres
            return None
1728 218 storres
        currentRangeSo = pobyso_bounds_to_range_sa_so(currentLowerBoundSa,
1729 218 storres
                                                      currentUpperBoundSa)
1730 218 storres
        # print "New interval:",
1731 218 storres
        # pobyso_autoprint(currentRangeSo)
1732 218 storres
        #print "Second Taylor expansion call."
1733 218 storres
        (polySo, intervalCenterSo, maxErrorSo) = \
1734 218 storres
            pobyso_taylor_expansion_no_change_var_so_so(functionSo, degreeSo,
1735 218 storres
                                                        currentRangeSo,
1736 218 storres
                                                        absoluteErrorTypeSo)
1737 218 storres
        #maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo, RRR)
1738 218 storres
        #print "Max errorSo:",
1739 218 storres
        #pobyso_autoprint(maxErrorSo)
1740 218 storres
        maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
1741 218 storres
        #print "Max errorSa:", maxErrorSa
1742 218 storres
        #print "Sollya prec:",
1743 218 storres
        #pobyso_autoprint(sollya_lib_get_prec(None))
1744 218 storres
    # End while
1745 218 storres
    sollya_lib_clear_obj(absoluteErrorTypeSo)
1746 218 storres
    itpSo           = pobyso_constant_from_int_sa_so(floor(sollyaPrecSa/3))
1747 218 storres
    ftpSo           = pobyso_constant_from_int_sa_so(floor(2*sollyaPrecSa/3))
1748 218 storres
    maxPrecSo       = pobyso_constant_from_int_sa_so(sollyaPrecSa)
1749 218 storres
    approxAccurSo   = pobyso_constant_sa_so(RR(approxAccurSa))
1750 218 storres
    print "About to call polynomial rounding with:"
1751 218 storres
    print "polySo: ",           ; pobyso_autoprint(polySo)
1752 218 storres
    print "functionSo: ",       ; pobyso_autoprint(functionSo)
1753 218 storres
    print "intervalCenterSo: ", ; pobyso_autoprint(intervalCenterSo)
1754 218 storres
    print "currentRangeSo: ",   ; pobyso_autoprint(currentRangeSo)
1755 218 storres
    print "itpSo: ",            ; pobyso_autoprint(itpSo)
1756 218 storres
    print "ftpSo: ",            ; pobyso_autoprint(ftpSo)
1757 218 storres
    print "maxPrecSo: ",        ; pobyso_autoprint(maxPrecSo)
1758 218 storres
    print "approxAccurSo: ",    ; pobyso_autoprint(approxAccurSo)
1759 218 storres
    (roundedPolySo, roundedPolyMaxErrSo) = \
1760 228 storres
    pobyso_round_coefficients_progressive_so_so(polySo,
1761 228 storres
                                                functionSo,
1762 228 storres
                                                maxPrecSo,
1763 228 storres
                                                currentRangeSo,
1764 228 storres
                                                intervalCenterSo,
1765 228 storres
                                                maxErrorSo,
1766 228 storres
                                                approxAccurSo,
1767 228 storres
                                                debug = True)
1768 218 storres
1769 218 storres
    sollya_lib_clear_obj(polySo)
1770 218 storres
    sollya_lib_clear_obj(maxErrorSo)
1771 218 storres
    sollya_lib_clear_obj(itpSo)
1772 218 storres
    sollya_lib_clear_obj(ftpSo)
1773 218 storres
    sollya_lib_clear_obj(approxAccurSo)
1774 226 storres
    if sollyaPrecChanged:
1775 226 storres
        pobyso_set_prec_so_so(initialSollyaPrecSo)
1776 226 storres
    sollya_lib_clear_obj(initialSollyaPrecSo)
1777 218 storres
    print "1: ", ; pobyso_autoprint(roundedPolySo)
1778 218 storres
    print "2: ", ; pobyso_autoprint(currentRangeSo)
1779 218 storres
    print "3: ", ; pobyso_autoprint(intervalCenterSo)
1780 218 storres
    print "4: ", ; pobyso_autoprint(roundedPolyMaxErrSo)
1781 218 storres
    return (roundedPolySo, currentRangeSo, intervalCenterSo, roundedPolyMaxErrSo)
1782 219 storres
# End slz_compute_polynomial_and_interval_02
1783 218 storres
1784 122 storres
def slz_compute_reduced_polynomial(matrixRow,
1785 98 storres
                                    knownMonomials,
1786 106 storres
                                    var1,
1787 98 storres
                                    var1Bound,
1788 106 storres
                                    var2,
1789 99 storres
                                    var2Bound):
1790 98 storres
    """
1791 125 storres
    Compute a polynomial from a single reduced matrix row.
1792 122 storres
    This function was introduced in order to avoid the computation of the
1793 125 storres
    all the polynomials  from the full matrix (even those built from rows
1794 125 storres
    that do no verify the Coppersmith condition) as this may involves
1795 152 storres
    expensive operations over (large) integers.
1796 122 storres
    """
1797 122 storres
    ## Check arguments.
1798 122 storres
    if len(knownMonomials) == 0:
1799 122 storres
        return None
1800 122 storres
    # varNounds can be zero since 0^0 returns 1.
1801 122 storres
    if (var1Bound < 0) or (var2Bound < 0):
1802 122 storres
        return None
1803 122 storres
    ## Initialisations.
1804 122 storres
    polynomialRing = knownMonomials[0].parent()
1805 122 storres
    currentPolynomial = polynomialRing(0)
1806 123 storres
    # TODO: use zip instead of indices.
1807 122 storres
    for colIndex in xrange(0, len(knownMonomials)):
1808 122 storres
        currentCoefficient = matrixRow[colIndex]
1809 122 storres
        if currentCoefficient != 0:
1810 122 storres
            #print "Current coefficient:", currentCoefficient
1811 122 storres
            currentMonomial = knownMonomials[colIndex]
1812 122 storres
            #print "Monomial as multivariate polynomial:", \
1813 122 storres
            #currentMonomial, type(currentMonomial)
1814 122 storres
            degreeInVar1 = currentMonomial.degree(var1)
1815 123 storres
            #print "Degree in var1", var1, ":", degreeInVar1
1816 122 storres
            degreeInVar2 = currentMonomial.degree(var2)
1817 123 storres
            #print "Degree in var2", var2, ":", degreeInVar2
1818 122 storres
            if degreeInVar1 > 0:
1819 122 storres
                currentCoefficient = \
1820 123 storres
                    currentCoefficient / (var1Bound^degreeInVar1)
1821 122 storres
                #print "varBound1 in degree:", var1Bound^degreeInVar1
1822 122 storres
                #print "Current coefficient(1)", currentCoefficient
1823 122 storres
            if degreeInVar2 > 0:
1824 122 storres
                currentCoefficient = \
1825 123 storres
                    currentCoefficient / (var2Bound^degreeInVar2)
1826 122 storres
                #print "Current coefficient(2)", currentCoefficient
1827 122 storres
            #print "Current reduced monomial:", (currentCoefficient * \
1828 122 storres
            #                                    currentMonomial)
1829 122 storres
            currentPolynomial += (currentCoefficient * currentMonomial)
1830 122 storres
            #print "Current polynomial:", currentPolynomial
1831 122 storres
        # End if
1832 122 storres
    # End for colIndex.
1833 122 storres
    #print "Type of the current polynomial:", type(currentPolynomial)
1834 122 storres
    return(currentPolynomial)
1835 122 storres
# End slz_compute_reduced_polynomial
1836 122 storres
#
1837 122 storres
def slz_compute_reduced_polynomials(reducedMatrix,
1838 122 storres
                                        knownMonomials,
1839 122 storres
                                        var1,
1840 122 storres
                                        var1Bound,
1841 122 storres
                                        var2,
1842 122 storres
                                        var2Bound):
1843 122 storres
    """
1844 122 storres
    Legacy function, use slz_compute_reduced_polynomials_list
1845 122 storres
    """
1846 122 storres
    return(slz_compute_reduced_polynomials_list(reducedMatrix,
1847 122 storres
                                                knownMonomials,
1848 122 storres
                                                var1,
1849 122 storres
                                                var1Bound,
1850 122 storres
                                                var2,
1851 122 storres
                                                var2Bound)
1852 122 storres
    )
1853 177 storres
#
1854 122 storres
def slz_compute_reduced_polynomials_list(reducedMatrix,
1855 152 storres
                                         knownMonomials,
1856 152 storres
                                         var1,
1857 152 storres
                                         var1Bound,
1858 152 storres
                                         var2,
1859 152 storres
                                         var2Bound):
1860 122 storres
    """
1861 98 storres
    From a reduced matrix, holding the coefficients, from a monomials list,
1862 98 storres
    from the bounds of each variable, compute the corresponding polynomials
1863 98 storres
    scaled back by dividing by the "right" powers of the variables bounds.
1864 99 storres
1865 99 storres
    The elements in knownMonomials must be of the "right" polynomial type.
1866 172 storres
    They set the polynomial type of the output polynomials in list.
1867 152 storres
    @param reducedMatrix:  the reduced matrix as output from LLL;
1868 152 storres
    @param kwnonMonomials: the ordered list of the monomials used to
1869 152 storres
                           build the polynomials;
1870 152 storres
    @param var1:           the first variable (of the "right" type);
1871 152 storres
    @param var1Bound:      the first variable bound;
1872 152 storres
    @param var2:           the second variable (of the "right" type);
1873 152 storres
    @param var2Bound:      the second variable bound.
1874 152 storres
    @return: a list of polynomials obtained with the reduced coefficients
1875 152 storres
             and scaled down with the bounds
1876 98 storres
    """
1877 99 storres
1878 98 storres
    # TODO: check input arguments.
1879 98 storres
    reducedPolynomials = []
1880 106 storres
    #print "type var1:", type(var1), " - type var2:", type(var2)
1881 98 storres
    for matrixRow in reducedMatrix.rows():
1882 102 storres
        currentPolynomial = 0
1883 98 storres
        for colIndex in xrange(0, len(knownMonomials)):
1884 98 storres
            currentCoefficient = matrixRow[colIndex]
1885 106 storres
            if currentCoefficient != 0:
1886 106 storres
                #print "Current coefficient:", currentCoefficient
1887 106 storres
                currentMonomial = knownMonomials[colIndex]
1888 106 storres
                parentRing = currentMonomial.parent()
1889 106 storres
                #print "Monomial as multivariate polynomial:", \
1890 106 storres
                #currentMonomial, type(currentMonomial)
1891 106 storres
                degreeInVar1 = currentMonomial.degree(parentRing(var1))
1892 106 storres
                #print "Degree in var", var1, ":", degreeInVar1
1893 106 storres
                degreeInVar2 = currentMonomial.degree(parentRing(var2))
1894 106 storres
                #print "Degree in var", var2, ":", degreeInVar2
1895 106 storres
                if degreeInVar1 > 0:
1896 167 storres
                    currentCoefficient /= var1Bound^degreeInVar1
1897 106 storres
                    #print "varBound1 in degree:", var1Bound^degreeInVar1
1898 106 storres
                    #print "Current coefficient(1)", currentCoefficient
1899 106 storres
                if degreeInVar2 > 0:
1900 167 storres
                    currentCoefficient /= var2Bound^degreeInVar2
1901 106 storres
                    #print "Current coefficient(2)", currentCoefficient
1902 106 storres
                #print "Current reduced monomial:", (currentCoefficient * \
1903 106 storres
                #                                    currentMonomial)
1904 106 storres
                currentPolynomial += (currentCoefficient * currentMonomial)
1905 168 storres
                #if degreeInVar1 == 0 and degreeInVar2 == 0:
1906 168 storres
                    #print "!!!! constant term !!!!"
1907 106 storres
                #print "Current polynomial:", currentPolynomial
1908 106 storres
            # End if
1909 106 storres
        # End for colIndex.
1910 99 storres
        #print "Type of the current polynomial:", type(currentPolynomial)
1911 99 storres
        reducedPolynomials.append(currentPolynomial)
1912 98 storres
    return reducedPolynomials
1913 177 storres
# End slz_compute_reduced_polynomials_list.
1914 98 storres
1915 177 storres
def slz_compute_reduced_polynomials_list_from_rows(rowsList,
1916 177 storres
                                                   knownMonomials,
1917 177 storres
                                                   var1,
1918 177 storres
                                                   var1Bound,
1919 177 storres
                                                   var2,
1920 177 storres
                                                   var2Bound):
1921 177 storres
    """
1922 177 storres
    From a list of rows, holding the coefficients, from a monomials list,
1923 177 storres
    from the bounds of each variable, compute the corresponding polynomials
1924 177 storres
    scaled back by dividing by the "right" powers of the variables bounds.
1925 177 storres
1926 177 storres
    The elements in knownMonomials must be of the "right" polynomial type.
1927 177 storres
    They set the polynomial type of the output polynomials in list.
1928 177 storres
    @param rowsList:       the reduced matrix as output from LLL;
1929 177 storres
    @param kwnonMonomials: the ordered list of the monomials used to
1930 177 storres
                           build the polynomials;
1931 177 storres
    @param var1:           the first variable (of the "right" type);
1932 177 storres
    @param var1Bound:      the first variable bound;
1933 177 storres
    @param var2:           the second variable (of the "right" type);
1934 177 storres
    @param var2Bound:      the second variable bound.
1935 177 storres
    @return: a list of polynomials obtained with the reduced coefficients
1936 177 storres
             and scaled down with the bounds
1937 177 storres
    """
1938 177 storres
1939 177 storres
    # TODO: check input arguments.
1940 177 storres
    reducedPolynomials = []
1941 177 storres
    #print "type var1:", type(var1), " - type var2:", type(var2)
1942 177 storres
    for matrixRow in rowsList:
1943 177 storres
        currentPolynomial = 0
1944 177 storres
        for colIndex in xrange(0, len(knownMonomials)):
1945 177 storres
            currentCoefficient = matrixRow[colIndex]
1946 177 storres
            if currentCoefficient != 0:
1947 177 storres
                #print "Current coefficient:", currentCoefficient
1948 177 storres
                currentMonomial = knownMonomials[colIndex]
1949 177 storres
                parentRing = currentMonomial.parent()
1950 177 storres
                #print "Monomial as multivariate polynomial:", \
1951 177 storres
                #currentMonomial, type(currentMonomial)
1952 177 storres
                degreeInVar1 = currentMonomial.degree(parentRing(var1))
1953 177 storres
                #print "Degree in var", var1, ":", degreeInVar1
1954 177 storres
                degreeInVar2 = currentMonomial.degree(parentRing(var2))
1955 177 storres
                #print "Degree in var", var2, ":", degreeInVar2
1956 177 storres
                if degreeInVar1 > 0:
1957 177 storres
                    currentCoefficient /= var1Bound^degreeInVar1
1958 177 storres
                    #print "varBound1 in degree:", var1Bound^degreeInVar1
1959 177 storres
                    #print "Current coefficient(1)", currentCoefficient
1960 177 storres
                if degreeInVar2 > 0:
1961 177 storres
                    currentCoefficient /= var2Bound^degreeInVar2
1962 177 storres
                    #print "Current coefficient(2)", currentCoefficient
1963 177 storres
                #print "Current reduced monomial:", (currentCoefficient * \
1964 177 storres
                #                                    currentMonomial)
1965 177 storres
                currentPolynomial += (currentCoefficient * currentMonomial)
1966 177 storres
                #if degreeInVar1 == 0 and degreeInVar2 == 0:
1967 177 storres
                    #print "!!!! constant term !!!!"
1968 177 storres
                #print "Current polynomial:", currentPolynomial
1969 177 storres
            # End if
1970 177 storres
        # End for colIndex.
1971 177 storres
        #print "Type of the current polynomial:", type(currentPolynomial)
1972 177 storres
        reducedPolynomials.append(currentPolynomial)
1973 177 storres
    return reducedPolynomials
1974 177 storres
# End slz_compute_reduced_polynomials_list_from_rows.
1975 177 storres
#
1976 114 storres
def slz_compute_scaled_function(functionSa,
1977 114 storres
                                lowerBoundSa,
1978 114 storres
                                upperBoundSa,
1979 156 storres
                                floatingPointPrecSa,
1980 156 storres
                                debug=False):
1981 72 storres
    """
1982 72 storres
    From a function, compute the scaled function whose domain
1983 72 storres
    is included in [1, 2) and whose image is also included in [1,2).
1984 72 storres
    Return a tuple:
1985 72 storres
    [0]: the scaled function
1986 72 storres
    [1]: the scaled domain lower bound
1987 72 storres
    [2]: the scaled domain upper bound
1988 72 storres
    [3]: the scaled image lower bound
1989 72 storres
    [4]: the scaled image upper bound
1990 72 storres
    """
1991 177 storres
    ## The variable can be called anything.
1992 80 storres
    x = functionSa.variables()[0]
1993 72 storres
    # Scalling the domain -> [1,2[.
1994 72 storres
    boundsIntervalRifSa = RealIntervalField(floatingPointPrecSa)
1995 72 storres
    domainBoundsIntervalSa = boundsIntervalRifSa(lowerBoundSa, upperBoundSa)
1996 166 storres
    (invDomainScalingExpressionSa, domainScalingExpressionSa) = \
1997 80 storres
        slz_interval_scaling_expression(domainBoundsIntervalSa, x)
1998 156 storres
    if debug:
1999 156 storres
        print "domainScalingExpression for argument :", \
2000 156 storres
        invDomainScalingExpressionSa
2001 190 storres
        print "function: ", functionSa
2002 190 storres
    ff = functionSa.subs({x : domainScalingExpressionSa})
2003 190 storres
    ## Bless expression as a function.
2004 190 storres
    ff = ff.function(x)
2005 72 storres
    #ff = f.subs_expr(x==domainScalingExpressionSa)
2006 177 storres
    #domainScalingFunction(x) = invDomainScalingExpressionSa
2007 177 storres
    domainScalingFunction = invDomainScalingExpressionSa.function(x)
2008 151 storres
    scaledLowerBoundSa = \
2009 151 storres
        domainScalingFunction(lowerBoundSa).n(prec=floatingPointPrecSa)
2010 151 storres
    scaledUpperBoundSa = \
2011 151 storres
        domainScalingFunction(upperBoundSa).n(prec=floatingPointPrecSa)
2012 156 storres
    if debug:
2013 156 storres
        print 'ff:', ff, "- Domain:", scaledLowerBoundSa, \
2014 156 storres
              scaledUpperBoundSa
2015 254 storres
    ## If both bounds are negative, swap them.
2016 254 storres
    if lowerBoundSa < 0 and upperBoundSa < 0:
2017 254 storres
        scaledLowerBoundSa, scaledUpperBoundSa = \
2018 254 storres
        scaledUpperBoundSa,scaledLowerBoundSa
2019 72 storres
    #
2020 72 storres
    # Scalling the image -> [1,2[.
2021 151 storres
    flbSa = ff(scaledLowerBoundSa).n(prec=floatingPointPrecSa)
2022 151 storres
    fubSa = ff(scaledUpperBoundSa).n(prec=floatingPointPrecSa)
2023 72 storres
    if flbSa <= fubSa: # Increasing
2024 72 storres
        imageBinadeBottomSa = floor(flbSa.log2())
2025 72 storres
    else: # Decreasing
2026 72 storres
        imageBinadeBottomSa = floor(fubSa.log2())
2027 156 storres
    if debug:
2028 156 storres
        print 'ff:', ff, '- Image:', flbSa, fubSa, imageBinadeBottomSa
2029 72 storres
    imageBoundsIntervalSa = boundsIntervalRifSa(flbSa, fubSa)
2030 166 storres
    (invImageScalingExpressionSa,imageScalingExpressionSa) = \
2031 80 storres
        slz_interval_scaling_expression(imageBoundsIntervalSa, x)
2032 156 storres
    if debug:
2033 156 storres
        print "imageScalingExpression for argument :", \
2034 156 storres
              invImageScalingExpressionSa
2035 72 storres
    iis = invImageScalingExpressionSa.function(x)
2036 72 storres
    fff = iis.subs({x:ff})
2037 156 storres
    if debug:
2038 156 storres
        print "fff:", fff,
2039 156 storres
        print " - Image:", fff(scaledLowerBoundSa), fff(scaledUpperBoundSa)
2040 72 storres
    return([fff, scaledLowerBoundSa, scaledUpperBoundSa, \
2041 72 storres
            fff(scaledLowerBoundSa), fff(scaledUpperBoundSa)])
2042 151 storres
# End slz_compute_scaled_function
2043 72 storres
2044 179 storres
def slz_fix_bounds_for_binades(lowerBound,
2045 179 storres
                               upperBound,
2046 190 storres
                               func = None,
2047 179 storres
                               domainDirection = -1,
2048 179 storres
                               imageDirection  = -1):
2049 179 storres
    """
2050 179 storres
    Assuming the function is increasing or decreasing over the
2051 179 storres
    [lowerBound, upperBound] interval, return a lower bound lb and
2052 179 storres
    an upper bound ub such that:
2053 179 storres
    - lb and ub belong to the same binade;
2054 179 storres
    - func(lb) and func(ub) belong to the same binade.
2055 179 storres
    domainDirection indicate how bounds move to fit into the same binade:
2056 179 storres
    - a negative value move the upper bound down;
2057 179 storres
    - a positive value move the lower bound up.
2058 179 storres
    imageDirection indicate how bounds move in order to have their image
2059 179 storres
    fit into the same binade, variation of the function is also condidered.
2060 179 storres
    For an increasing function:
2061 179 storres
    - negative value moves the upper bound down (and its image value as well);
2062 179 storres
    - a positive values moves the lower bound up (and its image value as well);
2063 179 storres
    For a decreasing function it is the other way round.
2064 179 storres
    """
2065 179 storres
    ## Arguments check
2066 179 storres
    if lowerBound > upperBound:
2067 179 storres
        return None
2068 190 storres
    if lowerBound == upperBound:
2069 190 storres
        return (lowerBound, upperBound)
2070 179 storres
    if func is None:
2071 179 storres
        return None
2072 179 storres
    #
2073 179 storres
    #varFunc = func.variables()[0]
2074 179 storres
    lb = lowerBound
2075 179 storres
    ub = upperBound
2076 179 storres
    lbBinade = slz_compute_binade(lb)
2077 179 storres
    ubBinade = slz_compute_binade(ub)
2078 179 storres
    ## Domain binade.
2079 179 storres
    while lbBinade != ubBinade:
2080 179 storres
        newIntervalWidth = (ub - lb) / 2
2081 179 storres
        if domainDirection < 0:
2082 179 storres
            ub = lb + newIntervalWidth
2083 179 storres
            ubBinade = slz_compute_binade(ub)
2084 179 storres
        else:
2085 179 storres
            lb = lb + newIntervalWidth
2086 179 storres
            lbBinade = slz_compute_binade(lb)
2087 254 storres
    #print "sfbfb: lower bound:", lb.str(truncate=False)
2088 254 storres
    #print "sfbfb: upper bound:", ub.str(truncate=False)
2089 254 storres
    ## At this point, both bounds belond to the same binade.
2090 179 storres
    ## Image binade.
2091 179 storres
    if lb == ub:
2092 179 storres
        return (lb, ub)
2093 179 storres
    lbImg = func(lb)
2094 179 storres
    ubImg = func(ub)
2095 254 storres
    funcIsInc = ((ubImg - lbImg) >= 0)
2096 179 storres
    lbImgBinade = slz_compute_binade(lbImg)
2097 179 storres
    ubImgBinade = slz_compute_binade(ubImg)
2098 179 storres
    while lbImgBinade != ubImgBinade:
2099 179 storres
        newIntervalWidth = (ub - lb) / 2
2100 179 storres
        if imageDirection < 0:
2101 179 storres
            if funcIsInc:
2102 179 storres
                ub = lb + newIntervalWidth
2103 179 storres
                ubImgBinade = slz_compute_binade(func(ub))
2104 179 storres
                #print ubImgBinade
2105 179 storres
            else:
2106 179 storres
                lb = lb + newIntervalWidth
2107 179 storres
                lbImgBinade = slz_compute_binade(func(lb))
2108 179 storres
                #print lbImgBinade
2109 179 storres
        else:
2110 179 storres
            if funcIsInc:
2111 179 storres
                lb = lb + newIntervalWidth
2112 179 storres
                lbImgBinade = slz_compute_binade(func(lb))
2113 179 storres
                #print lbImgBinade
2114 179 storres
            else:
2115 179 storres
                ub = lb + newIntervalWidth
2116 179 storres
                ubImgBinade = slz_compute_binade(func(ub))
2117 179 storres
                #print ubImgBinade
2118 179 storres
    # End while lbImgBinade != ubImgBinade:
2119 179 storres
    return (lb, ub)
2120 179 storres
# End slz_fix_bounds_for_binades.
2121 179 storres
2122 79 storres
def slz_float_poly_of_float_to_rat_poly_of_rat(polyOfFloat):
2123 79 storres
    # Create a polynomial over the rationals.
2124 179 storres
    ratPolynomialRing = QQ[str(polyOfFloat.variables()[0])]
2125 179 storres
    return(ratPolynomialRing(polyOfFloat))
2126 86 storres
# End slz_float_poly_of_float_to_rat_poly_of_rat.
2127 81 storres
2128 188 storres
def slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(polyOfFloat):
2129 188 storres
    """
2130 188 storres
     Create a polynomial over the rationals where all denominators are
2131 188 storres
     powers of two.
2132 188 storres
    """
2133 188 storres
    polyVariable = polyOfFloat.variables()[0]
2134 188 storres
    RPR = QQ[str(polyVariable)]
2135 188 storres
    polyCoeffs      = polyOfFloat.coefficients()
2136 188 storres
    #print polyCoeffs
2137 188 storres
    polyExponents   = polyOfFloat.exponents()
2138 188 storres
    #print polyExponents
2139 188 storres
    polyDenomPtwoCoeffs = []
2140 188 storres
    for coeff in polyCoeffs:
2141 188 storres
        polyDenomPtwoCoeffs.append(sno_float_to_rat_pow_of_two_denom(coeff))
2142 188 storres
        #print "Converted coefficient:", sno_float_to_rat_pow_of_two_denom(coeff),
2143 188 storres
        #print type(sno_float_to_rat_pow_of_two_denom(coeff))
2144 188 storres
    ratPoly = RPR(0)
2145 188 storres
    #print type(ratPoly)
2146 188 storres
    ## !!! CAUTION !!! Do not use the RPR(coeff * polyVariagle^exponent)
2147 188 storres
    #  The coefficient becomes plainly wrong when exponent == 0.
2148 188 storres
    #  No clue as to why.
2149 188 storres
    for coeff, exponent in zip(polyDenomPtwoCoeffs, polyExponents):
2150 188 storres
        ratPoly += coeff * RPR(polyVariable^exponent)
2151 188 storres
    return ratPoly
2152 188 storres
# End slz_float_poly_of_float_to_rat_poly_of_rat.
2153 188 storres
2154 80 storres
def slz_get_intervals_and_polynomials(functionSa, degreeSa,
2155 63 storres
                                      lowerBoundSa,
2156 269 storres
                                      upperBoundSa,
2157 269 storres
                                      floatingPointPrecSa,
2158 269 storres
                                      internalSollyaPrecSa,
2159 269 storres
                                      approxAccurSa):
2160 60 storres
    """
2161 60 storres
    Under the assumption that:
2162 60 storres
    - functionSa is monotonic on the [lowerBoundSa, upperBoundSa] interval;
2163 60 storres
    - lowerBound and upperBound belong to the same binade.
2164 60 storres
    from a:
2165 60 storres
    - function;
2166 60 storres
    - a degree
2167 60 storres
    - a pair of bounds;
2168 60 storres
    - the floating-point precision we work on;
2169 60 storres
    - the internal Sollya precision;
2170 64 storres
    - the requested approximation error
2171 61 storres
    The initial interval is, possibly, splitted into smaller intervals.
2172 61 storres
    It return a list of tuples, each made of:
2173 72 storres
    - a first polynomial (without the changed variable f(x) = p(x-x0));
2174 79 storres
    - a second polynomial (with a changed variable f(x) = q(x))
2175 61 storres
    - the approximation interval;
2176 72 storres
    - the center, x0, of the interval;
2177 61 storres
    - the corresponding approximation error.
2178 100 storres
    TODO: fix endless looping for some parameters sets.
2179 60 storres
    """
2180 120 storres
    resultArray = []
2181 101 storres
    # Set Sollya to the necessary internal precision.
2182 226 storres
    sollyaPrecChangedSa = False
2183 226 storres
    (initialSollyaPrecSo, initialSollyaPrecSa) = pobyso_get_prec_so_so_sa()
2184 269 storres
    if internalSollyaPrecSa > initialSollyaPrecSa:
2185 226 storres
        if internalSollyaPrecSa <= 2:
2186 226 storres
            print inspect.stack()[0][3], ": precision change <=2 requested."
2187 85 storres
        pobyso_set_prec_sa_so(internalSollyaPrecSa)
2188 226 storres
        sollyaPrecChangedSa = True
2189 101 storres
    #
2190 80 storres
    x = functionSa.variables()[0] # Actual variable name can be anything.
2191 101 storres
    # Scaled function: [1=,2] -> [1,2].
2192 115 storres
    (fff, scaledLowerBoundSa, scaledUpperBoundSa,                             \
2193 115 storres
            scaledLowerBoundImageSa, scaledUpperBoundImageSa) =               \
2194 115 storres
                slz_compute_scaled_function(functionSa,                       \
2195 115 storres
                                            lowerBoundSa,                     \
2196 115 storres
                                            upperBoundSa,                     \
2197 80 storres
                                            floatingPointPrecSa)
2198 166 storres
    # In case bounds were in the negative real one may need to
2199 166 storres
    # switch scaled bounds.
2200 166 storres
    if scaledLowerBoundSa > scaledUpperBoundSa:
2201 166 storres
        scaledLowerBoundSa, scaledUpperBoundSa = \
2202 166 storres
            scaledUpperBoundSa, scaledLowerBoundSa
2203 166 storres
        #print "Switching!"
2204 218 storres
    print "Approximation accuracy: ", RR(approxAccurSa)
2205 61 storres
    # Prepare the arguments for the Taylor expansion computation with Sollya.
2206 159 storres
    functionSo = \
2207 159 storres
      pobyso_parse_string_sa_so(fff._assume_str().replace('_SAGE_VAR_', ''))
2208 60 storres
    degreeSo = pobyso_constant_from_int_sa_so(degreeSa)
2209 61 storres
    scaledBoundsSo = pobyso_bounds_to_range_sa_so(scaledLowerBoundSa,
2210 61 storres
                                                  scaledUpperBoundSa)
2211 176 storres
2212 60 storres
    realIntervalField = RealIntervalField(max(lowerBoundSa.parent().precision(),
2213 60 storres
                                              upperBoundSa.parent().precision()))
2214 176 storres
    currentScaledLowerBoundSa = scaledLowerBoundSa
2215 176 storres
    currentScaledUpperBoundSa = scaledUpperBoundSa
2216 176 storres
    while True:
2217 176 storres
        ## Compute the first Taylor expansion.
2218 176 storres
        print "Computing a Taylor expansion..."
2219 176 storres
        (polySo, boundsSo, intervalCenterSo, maxErrorSo) = \
2220 176 storres
            slz_compute_polynomial_and_interval(functionSo, degreeSo,
2221 176 storres
                                        currentScaledLowerBoundSa,
2222 176 storres
                                        currentScaledUpperBoundSa,
2223 218 storres
                                        approxAccurSa, internalSollyaPrecSa)
2224 176 storres
        print "...done."
2225 176 storres
        ## If slz_compute_polynomial_and_interval fails, it returns None.
2226 176 storres
        #  This value goes to the first variable: polySo. Other variables are
2227 176 storres
        #  not assigned and should not be tested.
2228 176 storres
        if polySo is None:
2229 176 storres
            print "slz_get_intervals_and_polynomials: Aborting and returning None!"
2230 176 storres
            if precChangedSa:
2231 226 storres
                pobyso_set_prec_so_so(initialSollyaPrecSo)
2232 226 storres
            sollya_lib_clear_obj(initialSollyaPrecSo)
2233 176 storres
            sollya_lib_clear_obj(functionSo)
2234 176 storres
            sollya_lib_clear_obj(degreeSo)
2235 176 storres
            sollya_lib_clear_obj(scaledBoundsSo)
2236 176 storres
            return None
2237 176 storres
        ## Add to the result array.
2238 176 storres
        ### Change variable stuff in Sollya x -> x0-x.
2239 176 storres
        changeVarExpressionSo = \
2240 176 storres
            sollya_lib_build_function_sub( \
2241 176 storres
                              sollya_lib_build_function_free_variable(),
2242 101 storres
                              sollya_lib_copy_obj(intervalCenterSo))
2243 176 storres
        polyVarChangedSo = \
2244 176 storres
                    sollya_lib_evaluate(polySo, changeVarExpressionSo)
2245 176 storres
        #### Get rid of the variable change Sollya stuff.
2246 115 storres
        sollya_lib_clear_obj(changeVarExpressionSo)
2247 176 storres
        resultArray.append((polySo, polyVarChangedSo, boundsSo,
2248 101 storres
                            intervalCenterSo, maxErrorSo))
2249 176 storres
        boundsSa = pobyso_range_to_interval_so_sa(boundsSo, realIntervalField)
2250 101 storres
        errorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
2251 176 storres
        print "Computed approximation error:", errorSa.n(digits=10)
2252 176 storres
        # If the error and interval are OK a the first try, just return.
2253 176 storres
        if (boundsSa.endpoints()[1] >= scaledUpperBoundSa) and \
2254 218 storres
            (errorSa <= approxAccurSa):
2255 269 storres
            if sollyaPrecChangedSa:
2256 226 storres
                pobyso_set_prec_so_so(initialSollyaPrecSo)
2257 226 storres
            sollya_lib_clear_obj(initialSollyaPrecSo)
2258 176 storres
            sollya_lib_clear_obj(functionSo)
2259 176 storres
            sollya_lib_clear_obj(degreeSo)
2260 176 storres
            sollya_lib_clear_obj(scaledBoundsSo)
2261 101 storres
            #print "Approximation error:", errorSa
2262 176 storres
            return resultArray
2263 176 storres
        ## The returned interval upper bound does not reach the requested upper
2264 176 storres
        #  upper bound: compute the next upper bound.
2265 176 storres
        ## The following ratio is always >= 1. If errorSa, we may want to
2266 176 storres
        #  enlarge the interval
2267 218 storres
        currentErrorRatio = approxAccurSa / errorSa
2268 176 storres
        ## --|--------------------------------------------------------------|--
2269 176 storres
        #  --|--------------------|--------------------------------------------
2270 176 storres
        #  --|----------------------------|------------------------------------
2271 176 storres
        ## Starting point for the next upper bound.
2272 101 storres
        boundsWidthSa = boundsSa.endpoints()[1] - boundsSa.endpoints()[0]
2273 101 storres
        # Compute the increment.
2274 176 storres
        newBoundsWidthSa = \
2275 176 storres
                        ((currentErrorRatio.log() / 10) + 1) * boundsWidthSa
2276 176 storres
        currentScaledLowerBoundSa = boundsSa.endpoints()[1]
2277 176 storres
        currentScaledUpperBoundSa = boundsSa.endpoints()[1] + newBoundsWidthSa
2278 176 storres
        # Take into account the original interval upper bound.
2279 176 storres
        if currentScaledUpperBoundSa > scaledUpperBoundSa:
2280 176 storres
            currentScaledUpperBoundSa = scaledUpperBoundSa
2281 176 storres
        if currentScaledUpperBoundSa == currentScaledLowerBoundSa:
2282 85 storres
            print "Can't shrink the interval anymore!"
2283 85 storres
            print "You should consider increasing the Sollya internal precision"
2284 85 storres
            print "or the polynomial degree."
2285 85 storres
            print "Giving up!"
2286 176 storres
            if precChangedSa:
2287 226 storres
                pobyso_set_prec_so_so(initialSollyaPrecSo)
2288 226 storres
            sollya_lib_clear_obj(initialSollyaPrecSo)
2289 85 storres
            sollya_lib_clear_obj(functionSo)
2290 85 storres
            sollya_lib_clear_obj(degreeSo)
2291 85 storres
            sollya_lib_clear_obj(scaledBoundsSo)
2292 85 storres
            return None
2293 176 storres
        # Compute the other expansions.
2294 176 storres
        # Test for insufficient precision.
2295 81 storres
# End slz_get_intervals_and_polynomials
2296 60 storres
2297 80 storres
def slz_interval_scaling_expression(boundsInterval, expVar):
2298 61 storres
    """
2299 151 storres
    Compute the scaling expression to map an interval that spans at most
2300 166 storres
    a single binade into [1, 2) and the inverse expression as well.
2301 165 storres
    If the interval spans more than one binade, result is wrong since
2302 165 storres
    scaling is only based on the lower bound.
2303 62 storres
    Not very sure that the transformation makes sense for negative numbers.
2304 61 storres
    """
2305 165 storres
    # The "one of the bounds is 0" special case. Here we consider
2306 165 storres
    # the interval as the subnormals binade.
2307 165 storres
    if boundsInterval.endpoints()[0] == 0 or boundsInterval.endpoints()[1] == 0:
2308 165 storres
        # The upper bound is (or should be) positive.
2309 165 storres
        if boundsInterval.endpoints()[0] == 0:
2310 165 storres
            if boundsInterval.endpoints()[1] == 0:
2311 165 storres
                return None
2312 165 storres
            binade = slz_compute_binade(boundsInterval.endpoints()[1])
2313 165 storres
            l2     = boundsInterval.endpoints()[1].abs().log2()
2314 165 storres
            # The upper bound is a power of two
2315 165 storres
            if binade == l2:
2316 165 storres
                scalingCoeff    = 2^(-binade)
2317 165 storres
                invScalingCoeff = 2^(binade)
2318 165 storres
                scalingOffset   = 1
2319 179 storres
                return \
2320 179 storres
                  ((scalingCoeff * expVar + scalingOffset).function(expVar),
2321 179 storres
                  ((expVar - scalingOffset) * invScalingCoeff).function(expVar))
2322 165 storres
            else:
2323 165 storres
                scalingCoeff    = 2^(-binade-1)
2324 165 storres
                invScalingCoeff = 2^(binade+1)
2325 165 storres
                scalingOffset   = 1
2326 165 storres
                return((scalingCoeff * expVar + scalingOffset),\
2327 165 storres
                    ((expVar - scalingOffset) * invScalingCoeff))
2328 165 storres
        # The lower bound is (or should be) negative.
2329 165 storres
        if boundsInterval.endpoints()[1] == 0:
2330 165 storres
            if boundsInterval.endpoints()[0] == 0:
2331 165 storres
                return None
2332 165 storres
            binade = slz_compute_binade(boundsInterval.endpoints()[0])
2333 165 storres
            l2     = boundsInterval.endpoints()[0].abs().log2()
2334 165 storres
            # The upper bound is a power of two
2335 165 storres
            if binade == l2:
2336 165 storres
                scalingCoeff    = -2^(-binade)
2337 165 storres
                invScalingCoeff = -2^(binade)
2338 165 storres
                scalingOffset   = 1
2339 165 storres
                return((scalingCoeff * expVar + scalingOffset),\
2340 165 storres
                    ((expVar - scalingOffset) * invScalingCoeff))
2341 165 storres
            else:
2342 165 storres
                scalingCoeff    = -2^(-binade-1)
2343 165 storres
                invScalingCoeff = -2^(binade+1)
2344 165 storres
                scalingOffset   = 1
2345 165 storres
                return((scalingCoeff * expVar + scalingOffset),\
2346 165 storres
                   ((expVar - scalingOffset) * invScalingCoeff))
2347 165 storres
    # General case
2348 165 storres
    lbBinade = slz_compute_binade(boundsInterval.endpoints()[0])
2349 165 storres
    ubBinade = slz_compute_binade(boundsInterval.endpoints()[1])
2350 165 storres
    # We allow for a single exception in binade spanning is when the
2351 165 storres
    # "outward bound" is a power of 2 and its binade is that of the
2352 165 storres
    # "inner bound" + 1.
2353 165 storres
    if boundsInterval.endpoints()[0] > 0:
2354 165 storres
        ubL2 = boundsInterval.endpoints()[1].abs().log2()
2355 165 storres
        if lbBinade != ubBinade:
2356 165 storres
            print "Different binades."
2357 165 storres
            if ubL2 != ubBinade:
2358 165 storres
                print "Not a power of 2."
2359 165 storres
                return None
2360 165 storres
            elif abs(ubBinade - lbBinade) > 1:
2361 165 storres
                print "Too large span:", abs(ubBinade - lbBinade)
2362 165 storres
                return None
2363 165 storres
    else:
2364 165 storres
        lbL2 = boundsInterval.endpoints()[0].abs().log2()
2365 165 storres
        if lbBinade != ubBinade:
2366 165 storres
            print "Different binades."
2367 165 storres
            if lbL2 != lbBinade:
2368 165 storres
                print "Not a power of 2."
2369 165 storres
                return None
2370 165 storres
            elif abs(ubBinade - lbBinade) > 1:
2371 165 storres
                print "Too large span:", abs(ubBinade - lbBinade)
2372 165 storres
                return None
2373 165 storres
    #print "Lower bound binade:", binade
2374 165 storres
    if boundsInterval.endpoints()[0] > 0:
2375 179 storres
        return \
2376 179 storres
            ((2^(-lbBinade) * expVar).function(expVar),
2377 179 storres
             (2^(lbBinade) * expVar).function(expVar))
2378 165 storres
    else:
2379 179 storres
        return \
2380 179 storres
            ((-(2^(-ubBinade)) * expVar).function(expVar),
2381 179 storres
             (-(2^(ubBinade)) * expVar).function(expVar))
2382 165 storres
"""
2383 165 storres
    # Code sent to attic. Should be the base for a
2384 165 storres
    # "slz_interval_translate_expression" rather than scale.
2385 165 storres
    # Extra control and special cases code  added in
2386 165 storres
    # slz_interval_scaling_expression could (should ?) be added to
2387 165 storres
    # this new function.
2388 62 storres
    # The scaling offset is only used for negative numbers.
2389 151 storres
    # When the absolute value of the lower bound is < 0.
2390 61 storres
    if abs(boundsInterval.endpoints()[0]) < 1:
2391 61 storres
        if boundsInterval.endpoints()[0] >= 0:
2392 62 storres
            scalingCoeff = 2^floor(boundsInterval.endpoints()[0].log2())
2393 62 storres
            invScalingCoeff = 1/scalingCoeff
2394 80 storres
            return((scalingCoeff * expVar,
2395 80 storres
                    invScalingCoeff * expVar))
2396 60 storres
        else:
2397 62 storres
            scalingCoeff = \
2398 62 storres
                2^(floor((-boundsInterval.endpoints()[0]).log2()) - 1)
2399 62 storres
            scalingOffset = -3 * scalingCoeff
2400 80 storres
            return((scalingCoeff * expVar + scalingOffset,
2401 80 storres
                    1/scalingCoeff * expVar + 3))
2402 61 storres
    else:
2403 61 storres
        if boundsInterval.endpoints()[0] >= 0:
2404 62 storres
            scalingCoeff = 2^floor(boundsInterval.endpoints()[0].log2())
2405 61 storres
            scalingOffset = 0
2406 80 storres
            return((scalingCoeff * expVar,
2407 80 storres
                    1/scalingCoeff * expVar))
2408 61 storres
        else:
2409 62 storres
            scalingCoeff = \
2410 62 storres
                2^(floor((-boundsInterval.endpoints()[1]).log2()))
2411 62 storres
            scalingOffset =  -3 * scalingCoeff
2412 62 storres
            #scalingOffset = 0
2413 80 storres
            return((scalingCoeff * expVar + scalingOffset,
2414 80 storres
                    1/scalingCoeff * expVar + 3))
2415 165 storres
"""
2416 151 storres
# End slz_interval_scaling_expression
2417 61 storres
2418 83 storres
def slz_interval_and_polynomial_to_sage(polyRangeCenterErrorSo):
2419 72 storres
    """
2420 72 storres
    Compute the Sage version of the Taylor polynomial and it's
2421 72 storres
    companion data (interval, center...)
2422 72 storres
    The input parameter is a five elements tuple:
2423 79 storres
    - [0]: the polyomial (without variable change), as polynomial over a
2424 79 storres
           real ring;
2425 79 storres
    - [1]: the polyomial (with variable change done in Sollya), as polynomial
2426 79 storres
           over a real ring;
2427 72 storres
    - [2]: the interval (as Sollya range);
2428 72 storres
    - [3]: the interval center;
2429 72 storres
    - [4]: the approximation error.
2430 72 storres
2431 218 storres
    The function returns a 5 elements tuple: formed with all the
2432 72 storres
    input elements converted into their Sollya counterpart.
2433 72 storres
    """
2434 233 storres
    #print "Sollya polynomial to convert:",
2435 233 storres
    #pobyso_autoprint(polyRangeCenterErrorSo)
2436 218 storres
    polynomialSa = pobyso_float_poly_so_sa(polyRangeCenterErrorSo[0])
2437 218 storres
    #print "Polynomial after first conversion: ", pobyso_autoprint(polyRangeCenterErrorSo[1])
2438 218 storres
    polynomialChangedVarSa = pobyso_float_poly_so_sa(polyRangeCenterErrorSo[1])
2439 60 storres
    intervalSa = \
2440 64 storres
            pobyso_get_interval_from_range_so_sa(polyRangeCenterErrorSo[2])
2441 60 storres
    centerSa = \
2442 64 storres
            pobyso_get_constant_as_rn_with_rf_so_sa(polyRangeCenterErrorSo[3])
2443 60 storres
    errorSa = \
2444 64 storres
            pobyso_get_constant_as_rn_with_rf_so_sa(polyRangeCenterErrorSo[4])
2445 64 storres
    return((polynomialSa, polynomialChangedVarSa, intervalSa, centerSa, errorSa))
2446 83 storres
    # End slz_interval_and_polynomial_to_sage
2447 62 storres
2448 269 storres
def slz_is_htrn(argument,
2449 269 storres
                function,
2450 269 storres
                targetAccuracy,
2451 269 storres
                targetRF = None,
2452 269 storres
                targetPlusOnePrecRF = None,
2453 269 storres
                quasiExactRF = None):
2454 172 storres
    """
2455 172 storres
      Check if an element (argument) of the domain of function (function)
2456 172 storres
      yields a HTRN case (rounding to next) for the target precision
2457 183 storres
      (as impersonated by targetRF) for a given accuracy (targetAccuracy).
2458 205 storres
2459 205 storres
      The strategy is:
2460 205 storres
      - compute the image at high (quasi-exact) precision;
2461 205 storres
      - round it to nearest to precision;
2462 205 storres
      - round it to exactly to (precision+1), the computed number has two
2463 205 storres
        midpoint neighbors;
2464 205 storres
      - check the distance between these neighbors and the quasi-exact value;
2465 205 storres
        - if none of them is closer than the targetAccuracy, return False,
2466 205 storres
        - else return true.
2467 205 storres
      - Powers of two are a special case when comparing the midpoint in
2468 205 storres
        the 0 direction..
2469 172 storres
    """
2470 183 storres
    ## Arguments filtering.
2471 183 storres
    ## TODO: filter the first argument for consistence.
2472 172 storres
    if targetRF is None:
2473 172 storres
        targetRF = argument.parent()
2474 172 storres
    ## Ditto for the real field holding the midpoints.
2475 172 storres
    if targetPlusOnePrecRF is None:
2476 172 storres
        targetPlusOnePrecRF = RealField(targetRF.prec()+1)
2477 183 storres
    ## If no quasiExactField is provided, create a high accuracy RealField.
2478 172 storres
    if quasiExactRF is None:
2479 172 storres
        quasiExactRF = RealField(1536)
2480 195 storres
    function                      = function.function(function.variables()[0])
2481 172 storres
    exactArgument                 = quasiExactRF(argument)
2482 172 storres
    quasiExactValue               = function(exactArgument)
2483 172 storres
    roundedValue                  = targetRF(quasiExactValue)
2484 172 storres
    roundedValuePrecPlusOne       = targetPlusOnePrecRF(roundedValue)
2485 172 storres
    # Upper midpoint.
2486 172 storres
    roundedValuePrecPlusOneNext   = roundedValuePrecPlusOne.nextabove()
2487 172 storres
    # Lower midpoint.
2488 172 storres
    roundedValuePrecPlusOnePrev   = roundedValuePrecPlusOne.nextbelow()
2489 172 storres
    binade                        = slz_compute_binade(roundedValue)
2490 172 storres
    binadeCorrectedTargetAccuracy = targetAccuracy * 2^binade
2491 172 storres
    #print "Argument:", argument
2492 172 storres
    #print "f(x):", roundedValue, binade, floor(binade), ceil(binade)
2493 174 storres
    #print "Binade:", binade
2494 172 storres
    #print "binadeCorrectedTargetAccuracy:", \
2495 174 storres
    #binadeCorrectedTargetAccuracy.n(prec=100)
2496 172 storres
    #print "binadeCorrectedTargetAccuracy:", \
2497 172 storres
    #  binadeCorrectedTargetAccuracy.n(prec=100).str(base=2)
2498 172 storres
    #print "Upper midpoint:", \
2499 172 storres
    #  roundedValuePrecPlusOneNext.n(prec=targetPlusOnePrecRF.prec()).str(base=2)
2500 172 storres
    #print "Rounded value :", \
2501 172 storres
    #  roundedValuePrecPlusOne.n(prec=targetPlusOnePrecRF.prec()).str(base=2), \
2502 172 storres
    #  roundedValuePrecPlusOne.ulp().n(prec=2).str(base=2)
2503 172 storres
    #print "QuasiEx value :", quasiExactValue.n(prec=250).str(base=2)
2504 172 storres
    #print "Lower midpoint:", \
2505 172 storres
    #  roundedValuePrecPlusOnePrev.n(prec=targetPlusOnePrecRF.prec()).str(base=2)
2506 205 storres
    ## Make quasiExactValue = 0 a special case to move it out of the way.
2507 205 storres
    if quasiExactValue == 0:
2508 205 storres
        return False
2509 205 storres
    ## Begining of the general case : check with the midpoint of
2510 172 storres
    #  greatest absolute value.
2511 172 storres
    if quasiExactValue > 0:
2512 172 storres
        if abs(quasiExactRF(roundedValuePrecPlusOneNext) - quasiExactValue) <\
2513 172 storres
           binadeCorrectedTargetAccuracy:
2514 183 storres
            #print "Too close to the upper midpoint: ", \
2515 174 storres
            #abs(quasiExactRF(roundedValuePrecPlusOneNext) - quasiExactValue).n(prec=100)
2516 172 storres
            #print argument.n().str(base=16, \
2517 172 storres
            #  no_sci=False)
2518 172 storres
            #print "Lower midpoint:", \
2519 172 storres
            #  roundedValuePrecPlusOnePrev.n(prec=targetPlusOnePrecRF.prec()).str(base=2)
2520 172 storres
            #print "Value         :", \
2521 183 storres
            # quasiExactValue.n(prec=200).str(base=2)
2522 172 storres
            #print "Upper midpoint:", \
2523 172 storres
            #  roundedValuePrecPlusOneNext.n(prec=targetPlusOnePrecRF.prec()).str(base=2)
2524 172 storres
            return True
2525 205 storres
    else: # quasiExactValue < 0, the 0 case has been previously filtered out.
2526 172 storres
        if abs(quasiExactRF(roundedValuePrecPlusOnePrev) - quasiExactValue) < \
2527 172 storres
           binadeCorrectedTargetAccuracy:
2528 172 storres
            #print "Too close to the upper midpoint: ", \
2529 172 storres
            #  abs(quasiExactRF(roundedValuePrecPlusOneNext) - quasiExactValue).n(prec=100)
2530 172 storres
            #print argument.n().str(base=16, \
2531 172 storres
            #  no_sci=False)
2532 172 storres
            #print "Lower midpoint:", \
2533 172 storres
            #  roundedValuePrecPlusOnePrev.n(prec=targetPlusOnePrecRF.prec()).str(base=2)
2534 172 storres
            #print "Value         :", \
2535 172 storres
            #  quasiExactValue.n(prec=200).str(base=2)
2536 172 storres
            #print "Upper midpoint:", \
2537 172 storres
            #  roundedValuePrecPlusOneNext.n(prec=targetPlusOnePrecRF.prec()).str(base=2)
2538 172 storres
            #print
2539 172 storres
            return True
2540 172 storres
#2345678901234567890123456789012345678901234567890123456789012345678901234567890
2541 172 storres
    ## For the midpoint of smaller absolute value,
2542 172 storres
    #  split cases with the powers of 2.
2543 172 storres
    if sno_abs_is_power_of_two(roundedValue):
2544 172 storres
        if quasiExactValue > 0:
2545 172 storres
            if abs(quasiExactRF(roundedValuePrecPlusOnePrev) - quasiExactValue) <\
2546 172 storres
               binadeCorrectedTargetAccuracy / 2:
2547 172 storres
                #print "Lower midpoint:", \
2548 172 storres
                #  roundedValuePrecPlusOnePrev.n(prec=targetPlusOnePrecRF.prec()).str(base=2)
2549 172 storres
                #print "Value         :", \
2550 172 storres
                #  quasiExactValue.n(prec=200).str(base=2)
2551 172 storres
                #print "Upper midpoint:", \
2552 172 storres
                #  roundedValuePrecPlusOneNext.n(prec=targetPlusOnePrecRF.prec()).str(base=2)
2553 172 storres
                #print
2554 172 storres
                return True
2555 172 storres
        else:
2556 172 storres
            if abs(quasiExactRF(roundedValuePrecPlusOneNext) - quasiExactValue) < \
2557 172 storres
              binadeCorrectedTargetAccuracy / 2:
2558 172 storres
                #print "Lower midpoint:", \
2559 172 storres
                #  roundedValuePrecPlusOnePrev.n(prec=targetPlusOnePrecRF.prec()).str(base=2)
2560 172 storres
                #print "Value         :",
2561 172 storres
                #  quasiExactValue.n(prec=200).str(base=2)
2562 172 storres
                #print "Upper midpoint:",
2563 172 storres
                #  roundedValuePrecPlusOneNext.n(prec=targetPlusOnePrecRF.prec()).str(base=2)
2564 172 storres
                #print
2565 172 storres
                return True
2566 172 storres
#2345678901234567890123456789012345678901234567890123456789012345678901234567890
2567 172 storres
    else: ## Not a power of 2, regular comparison with the midpoint of
2568 172 storres
          #  smaller absolute value.
2569 172 storres
        if quasiExactValue > 0:
2570 172 storres
            if abs(quasiExactRF(roundedValuePrecPlusOnePrev) - quasiExactValue) < \
2571 172 storres
              binadeCorrectedTargetAccuracy:
2572 172 storres
                #print "Lower midpoint:", \
2573 172 storres
                #  roundedValuePrecPlusOnePrev.n(prec=targetPlusOnePrecRF.prec()).str(base=2)
2574 172 storres
                #print "Value         :", \
2575 172 storres
                #  quasiExactValue.n(prec=200).str(base=2)
2576 172 storres
                #print "Upper midpoint:", \
2577 172 storres
                #  roundedValuePrecPlusOneNext.n(prec=targetPlusOnePrecRF.prec()).str(base=2)
2578 172 storres
                #print
2579 172 storres
                return True
2580 172 storres
        else: # quasiExactValue <= 0
2581 172 storres
            if abs(quasiExactRF(roundedValuePrecPlusOneNext) - quasiExactValue) < \
2582 172 storres
              binadeCorrectedTargetAccuracy:
2583 172 storres
                #print "Lower midpoint:", \
2584 172 storres
                #  roundedValuePrecPlusOnePrev.n(prec=targetPlusOnePrecRF.prec()).str(base=2)
2585 172 storres
                #print "Value         :", \
2586 172 storres
                #  quasiExactValue.n(prec=200).str(base=2)
2587 172 storres
                #print "Upper midpoint:", \
2588 172 storres
                #  roundedValuePrecPlusOneNext.n(prec=targetPlusOnePrecRF.prec()).str(base=2)
2589 172 storres
                #print
2590 172 storres
                return True
2591 172 storres
    #print "distance to the upper midpoint:", \
2592 172 storres
    #  abs(quasiExactRF(roundedValuePrecPlusOneNext) - quasiExactValue).n(prec=100).str(base=2)
2593 172 storres
    #print "distance to the lower midpoint:", \
2594 172 storres
    #  abs(quasiExactRF(roundedValuePrecPlusOnePrev) - quasiExactValue).n(prec=100).str(base=2)
2595 172 storres
    return False
2596 172 storres
# End slz_is_htrn
2597 247 storres
#
2598 247 storres
def slz_pm1():
2599 247 storres
    """
2600 253 storres
    Compute a uniform RV in {-1, 1} (not zero).
2601 247 storres
    """
2602 247 storres
    ## function getrandbits(N) generates a long int with N random bits.
2603 276 storres
    #  Here it generates either 0 or 1. The multiplication by 2 and the
2604 276 storres
    #  subtraction of 1 make that:
2605 276 storres
    #  if getranbits(1) == 0 -> O * 2 - 1 = -1
2606 276 storres
    #  else                  -> 1 * 1 - 1 =  1.
2607 247 storres
    return getrandbits(1) * 2-1
2608 247 storres
# End slz_pm1.
2609 247 storres
#
2610 247 storres
def slz_random_proj_pm1(r, c):
2611 247 storres
    """
2612 247 storres
    r x c matrix with \pm 1 ({-1, 1}) coefficients
2613 247 storres
    """
2614 247 storres
    M = matrix(r, c)
2615 247 storres
    for i in range(0, r):
2616 247 storres
        for j in range (0, c):
2617 247 storres
            M[i,j] = slz_pm1()
2618 247 storres
    return M
2619 247 storres
# End random_proj_pm1.
2620 247 storres
#
2621 247 storres
def slz_random_proj_uniform(n, r, c):
2622 247 storres
    """
2623 277 storres
    r x c integer matrix with uniform n-bit integer elements.
2624 247 storres
    """
2625 247 storres
    M = matrix(r, c)
2626 247 storres
    for i in range(0, r):
2627 247 storres
        for j in range (0, c):
2628 247 storres
            M[i,j] = slz_uniform(n)
2629 247 storres
    return M
2630 247 storres
# End slz_random_proj_uniform.
2631 247 storres
#
2632 80 storres
def slz_rat_poly_of_int_to_poly_for_coppersmith(ratPolyOfInt,
2633 80 storres
                                                precision,
2634 80 storres
                                                targetHardnessToRound,
2635 80 storres
                                                variable1,
2636 80 storres
                                                variable2):
2637 80 storres
    """
2638 90 storres
    Creates a new multivariate polynomial with integer coefficients for use
2639 90 storres
     with the Coppersmith method.
2640 80 storres
    A the same time it computes :
2641 80 storres
    - 2^K (N);
2642 90 storres
    - 2^k (bound on the second variable)
2643 80 storres
    - lcm
2644 90 storres
2645 90 storres
    :param ratPolyOfInt: a polynomial with rational coefficients and integer
2646 90 storres
                         variables.
2647 90 storres
    :param precision: the precision of the floating-point coefficients.
2648 90 storres
    :param targetHardnessToRound: the hardness to round we want to check.
2649 90 storres
    :param variable1: the first variable of the polynomial (an expression).
2650 90 storres
    :param variable2: the second variable of the polynomial (an expression).
2651 90 storres
2652 90 storres
    :returns: a 4 elements tuple:
2653 90 storres
                - the polynomial;
2654 91 storres
                - the modulus (N);
2655 91 storres
                - the t bound;
2656 90 storres
                - the lcm used to compute the integral coefficients and the
2657 90 storres
                  module.
2658 80 storres
    """
2659 80 storres
    # Create a new integer polynomial ring.
2660 80 storres
    IP = PolynomialRing(ZZ, name=str(variable1) + "," + str(variable2))
2661 80 storres
    # Coefficients are issued in the increasing power order.
2662 80 storres
    ratPolyCoefficients = ratPolyOfInt.coefficients()
2663 91 storres
    # Print the reversed list for debugging.
2664 179 storres
    #print
2665 179 storres
    #print "Rational polynomial coefficients:", ratPolyCoefficients[::-1]
2666 94 storres
    # Build the list of number we compute the lcm of.
2667 80 storres
    coefficientDenominators = sro_denominators(ratPolyCoefficients)
2668 179 storres
    #print "Coefficient denominators:", coefficientDenominators
2669 80 storres
    coefficientDenominators.append(2^precision)
2670 170 storres
    coefficientDenominators.append(2^(targetHardnessToRound))
2671 87 storres
    leastCommonMultiple = lcm(coefficientDenominators)
2672 80 storres
    # Compute the expression corresponding to the new polynomial
2673 80 storres
    coefficientNumerators =  sro_numerators(ratPolyCoefficients)
2674 91 storres
    #print coefficientNumerators
2675 80 storres
    polynomialExpression = 0
2676 80 storres
    power = 0
2677 170 storres
    # Iterate over two lists at the same time, stop when the shorter
2678 170 storres
    # (is this case coefficientsNumerators) is
2679 170 storres
    # exhausted. Both lists are ordered in the order of increasing powers
2680 170 storres
    # of variable1.
2681 80 storres
    for numerator, denominator in \
2682 94 storres
                        zip(coefficientNumerators, coefficientDenominators):
2683 80 storres
        multiplicator = leastCommonMultiple / denominator
2684 80 storres
        newCoefficient = numerator * multiplicator
2685 80 storres
        polynomialExpression += newCoefficient * variable1^power
2686 80 storres
        power +=1
2687 80 storres
    polynomialExpression += - variable2
2688 80 storres
    return (IP(polynomialExpression),
2689 170 storres
            leastCommonMultiple / 2^precision, # 2^K aka N.
2690 170 storres
            #leastCommonMultiple / 2^(targetHardnessToRound + 1), # tBound
2691 170 storres
            leastCommonMultiple / 2^(targetHardnessToRound), # tBound
2692 91 storres
            leastCommonMultiple) # If we want to make test computations.
2693 80 storres
2694 170 storres
# End slz_rat_poly_of_int_to_poly_for_coppersmith
2695 79 storres
2696 79 storres
def slz_rat_poly_of_rat_to_rat_poly_of_int(ratPolyOfRat,
2697 79 storres
                                          precision):
2698 79 storres
    """
2699 79 storres
    Makes a variable substitution into the input polynomial so that the output
2700 79 storres
    polynomial can take integer arguments.
2701 79 storres
    All variables of the input polynomial "have precision p". That is to say
2702 103 storres
    that they are rationals with denominator == 2^(precision - 1):
2703 103 storres
    x = y/2^(precision - 1).
2704 79 storres
    We "incorporate" these denominators into the coefficients with,
2705 79 storres
    respectively, the "right" power.
2706 79 storres
    """
2707 79 storres
    polynomialField = ratPolyOfRat.parent()
2708 91 storres
    polynomialVariable = ratPolyOfRat.variables()[0]
2709 91 storres
    #print "The polynomial field is:", polynomialField
2710 79 storres
    return \
2711 91 storres
        polynomialField(ratPolyOfRat.subs({polynomialVariable : \
2712 79 storres
                                   polynomialVariable/2^(precision-1)}))
2713 79 storres
2714 79 storres
# End slz_rat_poly_of_rat_to_rat_poly_of_int
2715 79 storres
2716 177 storres
def slz_reduce_and_test_base(matrixToReduce,
2717 177 storres
                             nAtAlpha,
2718 177 storres
                             monomialsCountSqrt):
2719 177 storres
    """
2720 177 storres
    Reduces the basis, tests the Coppersmith condition and returns
2721 177 storres
    a list of rows that comply with the condition.
2722 177 storres
    """
2723 177 storres
    ccComplientRowsList = []
2724 177 storres
    reducedMatrix = matrixToReduce.LLL(None)
2725 177 storres
    if not reducedMatrix.is_LLL_reduced():
2726 177 storres
        raise Exception("reducedMatrix is not actually reduced. Aborting!")
2727 177 storres
    else:
2728 177 storres
        print "reducedMatrix is actually reduced."
2729 177 storres
    print "N^alpha:", nAtAlpha.n()
2730 177 storres
    rowIndex = 0
2731 177 storres
    for row in reducedMatrix.rows():
2732 177 storres
        l2Norm = row.norm(2)
2733 177 storres
        print "L_2 norm for vector # ", rowIndex, "= ", RR(l2Norm), "*", \
2734 177 storres
                monomialsCountSqrt.n(), ". Is vector OK?",
2735 177 storres
        if (l2Norm * monomialsCountSqrt < nAtAlpha):
2736 177 storres
            ccComplientRowsList.append(row)
2737 177 storres
            print "True"
2738 177 storres
        else:
2739 177 storres
            print "False"
2740 177 storres
    # End for
2741 177 storres
    return ccComplientRowsList
2742 177 storres
# End slz_reduce_and_test_base
2743 115 storres
2744 247 storres
def slz_reduce_lll_proj(matToReduce, n):
2745 247 storres
    """
2746 247 storres
    Compute the transformation matrix that realizes an LLL reduction on
2747 247 storres
    the random uniform projected matrix.
2748 247 storres
    Return both the initial matrix "reduced" by the transformation matrix and
2749 247 storres
    the transformation matrix itself.
2750 247 storres
    """
2751 247 storres
    ## Compute the projected matrix.
2752 249 storres
    """
2753 249 storres
    # Random matrix elements {-2^(n-1),...,0,...,2^(n-1)-1}.
2754 247 storres
    matProjector = slz_random_proj_uniform(n,
2755 247 storres
                                           matToReduce.ncols(),
2756 247 storres
                                           matToReduce.nrows())
2757 249 storres
    """
2758 279 storres
    reductionOK = False
2759 279 storres
    while not reductionOK:
2760 279 storres
        # Random matrix elements in {-1,0,1}.
2761 279 storres
        matProjector = slz_random_proj_pm1(matToReduce.ncols(),
2762 279 storres
                                           matToReduce.nrows())
2763 279 storres
        matProjected = matToReduce * matProjector
2764 279 storres
        ## Build the argument matrix for LLL in such a way that the
2765 279 storres
        #  transformationmatrix is also returned. This matrix is obtained
2766 279 storres
        #  at almost no extra cost. An identity matrix must be appended to
2767 279 storres
        #  the left of the initial matrix. The transformation matrix will
2768 279 storres
        # will be recovered at the same location from the returned matrix .
2769 279 storres
        idMat = identity_matrix(matProjected.nrows())
2770 279 storres
        augmentedMatToReduce = idMat.augment(matProjected)
2771 279 storres
        try:
2772 279 storres
            reducedProjMat = \
2773 279 storres
                augmentedMatToReduce.LLL(algorithm='fpLLL:wrapper')
2774 279 storres
            reductionOK = True
2775 279 storres
        except ValueError:
2776 279 storres
            print "Problem with projected matrix."
2777 279 storres
    # Enb while not reduction OK
2778 279 storres
    #
2779 247 storres
    ## Recover the transformation matrix (the left part of the reduced matrix).
2780 247 storres
    #  We discard the reduced matrix itself.
2781 247 storres
    transMat = reducedProjMat.submatrix(0,
2782 247 storres
                                        0,
2783 247 storres
                                        reducedProjMat.nrows(),
2784 247 storres
                                        reducedProjMat.nrows())
2785 247 storres
    ## Return the initial matrix "reduced" and the transformation matrix tuple.
2786 247 storres
    return (transMat * matToReduce, transMat)
2787 247 storres
# End  slz_reduce_lll_proj.
2788 247 storres
#
2789 277 storres
def slz_reduce_lll_proj_02(matToReduce, n):
2790 277 storres
    """
2791 277 storres
    Compute the transformation matrix that realizes an LLL reduction on
2792 277 storres
    the random uniform projected matrix.
2793 277 storres
    Return both the initial matrix "reduced" by the transformation matrix and
2794 277 storres
    the transformation matrix itself.
2795 277 storres
    """
2796 277 storres
    ## Compute the projected matrix.
2797 277 storres
    """
2798 277 storres
    # Random matrix elements {-2^(n-1),...,0,...,2^(n-1)-1}.
2799 277 storres
    matProjector = slz_random_proj_uniform(n,
2800 277 storres
                                           matToReduce.ncols(),
2801 277 storres
                                           matToReduce.nrows())
2802 277 storres
    """
2803 277 storres
    # Random matrix elements in {-8,0,7} -> 4.
2804 277 storres
    matProjector = slz_random_proj_uniform(matToReduce.ncols(),
2805 277 storres
                                           matToReduce.nrows(),
2806 277 storres
                                           4)
2807 277 storres
    matProjected = matToReduce * matProjector
2808 277 storres
    ## Build the argument matrix for LLL in such a way that the transformation
2809 277 storres
    #  matrix is also returned. This matrix is obtained at almost no extra
2810 277 storres
    # cost. An identity matrix must be appended to
2811 277 storres
    #  the left of the initial matrix. The transformation matrix will
2812 277 storres
    # will be recovered at the same location from the returned matrix .
2813 277 storres
    idMat = identity_matrix(matProjected.nrows())
2814 277 storres
    augmentedMatToReduce = idMat.augment(matProjected)
2815 277 storres
    reducedProjMat = \
2816 277 storres
        augmentedMatToReduce.LLL(algorithm='fpLLL:wrapper')
2817 277 storres
    ## Recover the transformation matrix (the left part of the reduced matrix).
2818 277 storres
    #  We discard the reduced matrix itself.
2819 277 storres
    transMat = reducedProjMat.submatrix(0,
2820 277 storres
                                        0,
2821 277 storres
                                        reducedProjMat.nrows(),
2822 277 storres
                                        reducedProjMat.nrows())
2823 277 storres
    ## Return the initial matrix "reduced" and the transformation matrix tuple.
2824 277 storres
    return (transMat * matToReduce, transMat)
2825 277 storres
# End  slz_reduce_lll_proj_02.
2826 277 storres
#
2827 229 storres
def slz_resultant(poly1, poly2, elimVar, debug = False):
2828 205 storres
    """
2829 205 storres
    Compute the resultant for two polynomials for a given variable
2830 205 storres
    and return the (poly1, poly2, resultant) if the resultant
2831 205 storres
    is not 0.
2832 205 storres
    Return () otherwise.
2833 205 storres
    """
2834 205 storres
    polynomialRing0    = poly1.parent()
2835 205 storres
    resultantInElimVar = poly1.resultant(poly2,polynomialRing0(elimVar))
2836 213 storres
    if resultantInElimVar is None:
2837 229 storres
        if debug:
2838 229 storres
            print poly1
2839 229 storres
            print poly2
2840 229 storres
            print "have GCD = ", poly1.gcd(poly2)
2841 213 storres
        return None
2842 205 storres
    if resultantInElimVar.is_zero():
2843 229 storres
        if debug:
2844 229 storres
            print poly1
2845 229 storres
            print poly2
2846 229 storres
            print "have GCD = ", poly1.gcd(poly2)
2847 205 storres
        return None
2848 205 storres
    else:
2849 229 storres
        if debug:
2850 229 storres
            print poly1
2851 229 storres
            print poly2
2852 229 storres
            print "have resultant in t = ", resultantInElimVar
2853 205 storres
        return resultantInElimVar
2854 205 storres
# End slz_resultant.
2855 205 storres
#
2856 177 storres
def slz_resultant_tuple(poly1, poly2, elimVar):
2857 179 storres
    """
2858 179 storres
    Compute the resultant for two polynomials for a given variable
2859 179 storres
    and return the (poly1, poly2, resultant) if the resultant
2860 180 storres
    is not 0.
2861 179 storres
    Return () otherwise.
2862 179 storres
    """
2863 181 storres
    polynomialRing0    = poly1.parent()
2864 177 storres
    resultantInElimVar = poly1.resultant(poly2,polynomialRing0(elimVar))
2865 180 storres
    if resultantInElimVar.is_zero():
2866 177 storres
        return ()
2867 177 storres
    else:
2868 177 storres
        return (poly1, poly2, resultantInElimVar)
2869 177 storres
# End slz_resultant_tuple.
2870 177 storres
#
2871 247 storres
def slz_uniform(n):
2872 247 storres
    """
2873 253 storres
    Compute a uniform RV in [-2^(n-1), 2^(n-1)-1] (zero is included).
2874 247 storres
    """
2875 247 storres
    ## function getrandbits(n) generates a long int with n random bits.
2876 247 storres
    return getrandbits(n) - 2^(n-1)
2877 247 storres
# End slz_uniform.
2878 247 storres
#
2879 246 storres
sys.stderr.write("\t...sageSLZ loaded\n")