Statistiques
| Révision :

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

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