Statistiques
| Révision :

root / pobysoPythonSage / src / sageSLZ / sageRunSLZ.sage @ 252

Historique | Voir | Annoter | Télécharger (202,63 ko)

1 213 storres
r"""
2 213 storres
Main SLZ algorithm body in several versions.
3 213 storres
4 213 storres
AUTHORS:
5 213 storres
- S.T. (2015-10-10): initial version
6 213 storres
7 213 storres
Examples:
8 213 storres
    TODO
9 194 storres
"""
10 246 storres
sys.stderr.write("sage Runtime SLZ loading...\n")
11 213 storres
12 213 storres
def srs_compute_lattice_volume(inputFunction,
13 213 storres
                    inputLowerBound,
14 213 storres
                    inputUpperBound,
15 213 storres
                    alpha,
16 213 storres
                    degree,
17 213 storres
                    precision,
18 213 storres
                    emin,
19 213 storres
                    emax,
20 213 storres
                    targetHardnessToRound,
21 213 storres
                    debug = False):
22 213 storres
    """
23 213 storres
    Changes from V2:
24 213 storres
        Root search is changed:
25 213 storres
            - we compute the resultants in i and in t;
26 213 storres
            - we compute the roots set of each of these resultants;
27 213 storres
            - we combine all the possible pairs between the two sets;
28 213 storres
            - we check these pairs in polynomials for correctness.
29 213 storres
    Changes from V1:
30 213 storres
        1- check for roots as soon as a resultant is computed;
31 213 storres
        2- once a non null resultant is found, check for roots;
32 213 storres
        3- constant resultant == no root.
33 213 storres
    """
34 213 storres
35 213 storres
    if debug:
36 213 storres
        print "Function                :", inputFunction
37 213 storres
        print "Lower bound             :", inputLowerBound
38 213 storres
        print "Upper bounds            :", inputUpperBound
39 213 storres
        print "Alpha                   :", alpha
40 213 storres
        print "Degree                  :", degree
41 213 storres
        print "Precision               :", precision
42 213 storres
        print "Emin                    :", emin
43 213 storres
        print "Emax                    :", emax
44 213 storres
        print "Target hardness-to-round:", targetHardnessToRound
45 213 storres
        print
46 213 storres
    ## Important constants.
47 213 storres
    ### Stretch the interval if no error happens.
48 213 storres
    noErrorIntervalStretch = 1 + 2^(-5)
49 213 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
50 213 storres
    #   by the following factor.
51 213 storres
    noCoppersmithIntervalShrink = 1/2
52 213 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
53 213 storres
    #   shrink the interval by the following factor.
54 213 storres
    oneCoppersmithIntervalShrink = 3/4
55 213 storres
    #### If only null resultants are found, shrink the interval by the
56 213 storres
    #    following factor.
57 213 storres
    onlyNullResultantsShrink     = 3/4
58 213 storres
    ## Structures.
59 213 storres
    RRR         = RealField(precision)
60 213 storres
    RRIF        = RealIntervalField(precision)
61 213 storres
    ## Converting input bound into the "right" field.
62 213 storres
    lowerBound = RRR(inputLowerBound)
63 213 storres
    upperBound = RRR(inputUpperBound)
64 213 storres
    ## Before going any further, check domain and image binade conditions.
65 213 storres
    print inputFunction(1).n()
66 213 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
67 213 storres
    if output is None:
68 213 storres
        print "Invalid domain/image binades. Domain:",\
69 213 storres
        lowerBound, upperBound, "Images:", \
70 213 storres
        inputFunction(lowerBound), inputFunction(upperBound)
71 213 storres
        raise Exception("Invalid domain/image binades.")
72 213 storres
    lb = output[0] ; ub = output[1]
73 213 storres
    if lb != lowerBound or ub != upperBound:
74 213 storres
        print "lb:", lb, " - ub:", ub
75 213 storres
        print "Invalid domain/image binades. Domain:",\
76 213 storres
        lowerBound, upperBound, "Images:", \
77 213 storres
        inputFunction(lowerBound), inputFunction(upperBound)
78 213 storres
        raise Exception("Invalid domain/image binades.")
79 213 storres
    #
80 213 storres
    ## Progam initialization
81 213 storres
    ### Approximation polynomial accuracy and hardness to round.
82 213 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
83 213 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
84 213 storres
    ### Significand to integer conversion ratio.
85 213 storres
    toIntegerFactor           = 2^(precision-1)
86 213 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
87 213 storres
    ### Variables and rings for polynomials and root searching.
88 213 storres
    i=var('i')
89 213 storres
    t=var('t')
90 213 storres
    inputFunctionVariable = inputFunction.variables()[0]
91 213 storres
    function = inputFunction.subs({inputFunctionVariable:i})
92 213 storres
    #  Polynomial Rings over the integers, for root finding.
93 213 storres
    Zi = ZZ[i]
94 213 storres
    Zt = ZZ[t]
95 213 storres
    Zit = ZZ[i,t]
96 213 storres
    ## Number of iterations limit.
97 213 storres
    maxIter = 100000
98 213 storres
    #
99 231 storres
    ## Set the variable name in Sollya.
100 231 storres
    pobyso_name_free_variable_sa_so(str(function.variables()[0]))
101 213 storres
    ## Compute the scaled function and the degree, in their Sollya version
102 213 storres
    #  once for all.
103 213 storres
    (scaledf, sdlb, sdub, silb, siub) = \
104 213 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
105 213 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
106 213 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
107 213 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
108 213 storres
    #
109 213 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
110 213 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
111 213 storres
    (unscalingFunction, scalingFunction) = \
112 213 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
113 213 storres
    #print scalingFunction, unscalingFunction
114 213 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
115 213 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
116 213 storres
    if internalSollyaPrec < 192:
117 213 storres
        internalSollyaPrec = 192
118 213 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
119 213 storres
    print "Sollya internal precision:", internalSollyaPrec
120 213 storres
    ## Some variables.
121 213 storres
    ### General variables
122 213 storres
    lb                  = sdlb
123 213 storres
    ub                  = sdub
124 213 storres
    nbw                 = 0
125 213 storres
    intervalUlp         = ub.ulp()
126 213 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
127 213 storres
    ic                  = 0
128 213 storres
    icAsInt             = 0    # Set from ic.
129 213 storres
    solutionsSet        = set()
130 213 storres
    tsErrorWidth        = []
131 213 storres
    csErrorVectors      = []
132 213 storres
    csVectorsResultants = []
133 213 storres
    floatP              = 0  # Taylor polynomial.
134 213 storres
    floatPcv            = 0  # Ditto with variable change.
135 213 storres
    intvl               = "" # Taylor interval
136 213 storres
    terr                = 0  # Taylor error.
137 213 storres
    iterCount = 0
138 213 storres
    htrnSet = set()
139 213 storres
    ### Timers and counters.
140 213 storres
    wallTimeStart                   = 0
141 213 storres
    cpuTimeStart                    = 0
142 213 storres
    taylCondFailedCount             = 0
143 213 storres
    coppCondFailedCount             = 0
144 213 storres
    resultCondFailedCount           = 0
145 213 storres
    coppCondFailed                  = False
146 213 storres
    resultCondFailed                = False
147 213 storres
    globalResultsList               = []
148 213 storres
    basisConstructionsCount         = 0
149 213 storres
    basisConstructionsFullTime      = 0
150 213 storres
    basisConstructionTime           = 0
151 213 storres
    reductionsCount                 = 0
152 213 storres
    reductionsFullTime              = 0
153 213 storres
    reductionTime                   = 0
154 213 storres
    resultantsComputationsCount     = 0
155 213 storres
    resultantsComputationsFullTime  = 0
156 213 storres
    resultantsComputationTime       = 0
157 213 storres
    rootsComputationsCount          = 0
158 213 storres
    rootsComputationsFullTime       = 0
159 213 storres
    rootsComputationTime            = 0
160 213 storres
    print
161 213 storres
    ## Global times are started here.
162 213 storres
    wallTimeStart                   = walltime()
163 213 storres
    cpuTimeStart                    = cputime()
164 213 storres
    ## Main loop.
165 213 storres
    while True:
166 213 storres
        if lb >= sdub:
167 213 storres
            print "Lower bound reached upper bound."
168 213 storres
            break
169 213 storres
        if iterCount == maxIter:
170 213 storres
            print "Reached maxIter. Aborting"
171 213 storres
            break
172 213 storres
        iterCount += 1
173 213 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
174 213 storres
            "log2(numbers)."
175 213 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
176 213 storres
        prceSo = slz_compute_polynomial_and_interval(scaledfSo,
177 213 storres
                                                     degreeSo,
178 213 storres
                                                     lb,
179 213 storres
                                                     ub,
180 213 storres
                                                     polyApproxAccur)
181 213 storres
        ### Convert back the data into Sage space.
182 213 storres
        (floatP, floatPcv, intvl, ic, terr) = \
183 213 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
184 213 storres
                                                 prceSo[1], prceSo[2],
185 213 storres
                                                 prceSo[3]))
186 213 storres
        intvl = RRIF(intvl)
187 213 storres
        ## Clean-up Sollya stuff.
188 213 storres
        for elem in prceSo:
189 213 storres
            sollya_lib_clear_obj(elem)
190 213 storres
        #print  floatP, floatPcv, intvl, ic, terr
191 213 storres
        #print floatP
192 213 storres
        #print intvl.endpoints()[0].n(), \
193 213 storres
        #      ic.n(),
194 213 storres
        #intvl.endpoints()[1].n()
195 213 storres
        ### Check returned data.
196 213 storres
        #### Is approximation error OK?
197 213 storres
        if terr > polyApproxAccur:
198 213 storres
            exceptionErrorMess  = \
199 213 storres
                "Approximation failed - computed error:" + \
200 213 storres
                str(terr) + " - target error: "
201 213 storres
            exceptionErrorMess += \
202 213 storres
                str(polyApproxAccur) + ". Aborting!"
203 213 storres
            raise Exception(exceptionErrorMess)
204 213 storres
        #### Is lower bound OK?
205 213 storres
        if lb != intvl.endpoints()[0]:
206 213 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
207 213 storres
                               str(lb) + ". Aborting!"
208 213 storres
            raise Exception(exceptionErrorMess)
209 213 storres
        #### Set upper bound.
210 213 storres
        if ub > intvl.endpoints()[1]:
211 213 storres
            ub = intvl.endpoints()[1]
212 213 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
213 213 storres
            "log2(numbers)."
214 213 storres
            taylCondFailedCount += 1
215 213 storres
        #### Is interval not degenerate?
216 213 storres
        if lb >= ub:
217 213 storres
            exceptionErrorMess = "Degenerate interval: " + \
218 213 storres
                                "lowerBound(" + str(lb) +\
219 213 storres
                                ")>= upperBound(" + str(ub) + \
220 213 storres
                                "). Aborting!"
221 213 storres
            raise Exception(exceptionErrorMess)
222 213 storres
        #### Is interval center ok?
223 213 storres
        if ic <= lb or ic >= ub:
224 213 storres
            exceptionErrorMess =  "Invalid interval center for " + \
225 213 storres
                                str(lb) + ',' + str(ic) + ',' +  \
226 213 storres
                                str(ub) + ". Aborting!"
227 213 storres
            raise Exception(exceptionErrorMess)
228 213 storres
        ##### Current interval width and reset future interval width.
229 213 storres
        bw = ub - lb
230 213 storres
        nbw = 0
231 213 storres
        icAsInt = int(ic * toIntegerFactor)
232 213 storres
        #### The following ratio is always >= 1. In case we may want to
233 213 storres
        #    enlarge the interval
234 213 storres
        curTaylErrRat = polyApproxAccur / terr
235 213 storres
        ### Make the  integral transformations.
236 213 storres
        #### Bounds and interval center.
237 213 storres
        intIc = int(ic * toIntegerFactor)
238 213 storres
        intLb = int(lb * toIntegerFactor) - intIc
239 213 storres
        intUb = int(ub * toIntegerFactor) - intIc
240 213 storres
        #
241 213 storres
        #### Polynomials
242 213 storres
        basisConstructionTime         = cputime()
243 213 storres
        ##### To a polynomial with rational coefficients with rational arguments
244 213 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
245 213 storres
        ##### To a polynomial with rational coefficients with integer arguments
246 213 storres
        ratIntP = \
247 213 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
248 213 storres
        #####  Ultimately a multivariate polynomial with integer coefficients
249 213 storres
        #      with integer arguments.
250 213 storres
        coppersmithTuple = \
251 213 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
252 213 storres
                                                        precision,
253 213 storres
                                                        targetHardnessToRound,
254 213 storres
                                                        i, t)
255 213 storres
        #### Recover Coppersmith information.
256 213 storres
        intIntP = coppersmithTuple[0]
257 213 storres
        N = coppersmithTuple[1]
258 213 storres
        nAtAlpha = N^alpha
259 213 storres
        tBound = coppersmithTuple[2]
260 213 storres
        leastCommonMultiple = coppersmithTuple[3]
261 213 storres
        iBound = max(abs(intLb),abs(intUb))
262 213 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
263 213 storres
        basisConstructionsCount           += 1
264 213 storres
        reductionTime                     = cputime()
265 213 storres
        #### Compute the reduced polynomials.
266 213 storres
        ccReducedPolynomialsList =  \
267 213 storres
            slz_compute_coppersmith_reduced_polynomials_with_lattice_volume(intIntP,
268 213 storres
                                                        alpha,
269 213 storres
                                                        N,
270 213 storres
                                                        iBound,
271 213 storres
                                                        tBound)
272 213 storres
        if ccReducedPolynomialsList is None:
273 213 storres
            raise Exception("Reduction failed.")
274 213 storres
        reductionsFullTime    += cputime(reductionTime)
275 213 storres
        reductionsCount       += 1
276 213 storres
        if len(ccReducedPolynomialsList) < 2:
277 213 storres
            print "Nothing to form resultants with."
278 213 storres
            print
279 213 storres
            coppCondFailedCount += 1
280 213 storres
            coppCondFailed = True
281 213 storres
            ##### Apply a different shrink factor according to
282 213 storres
            #  the number of compliant polynomials.
283 213 storres
            if len(ccReducedPolynomialsList) == 0:
284 213 storres
                ub = lb + bw * noCoppersmithIntervalShrink
285 213 storres
            else: # At least one compliant polynomial.
286 213 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
287 213 storres
            if ub > sdub:
288 213 storres
                ub = sdub
289 213 storres
            if lb == ub:
290 213 storres
                raise Exception("Cant shrink interval \
291 213 storres
                anymore to get Coppersmith condition.")
292 213 storres
            nbw = 0
293 213 storres
            continue
294 213 storres
        #### We have at least two polynomials.
295 213 storres
        #    Let us try to compute resultants.
296 213 storres
        #    For each resultant computed, go for the solutions.
297 213 storres
        ##### Build the pairs list.
298 213 storres
        polyPairsList           = []
299 213 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
300 213 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
301 213 storres
                                         len(ccReducedPolynomialsList)):
302 213 storres
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
303 213 storres
                                      ccReducedPolynomialsList[polyInnerIndex]))
304 213 storres
        #### Actual root search.
305 213 storres
        rootsSet            = set()
306 213 storres
        hasNonNullResultant = False
307 213 storres
        for polyPair in polyPairsList:
308 213 storres
            if hasNonNullResultant:
309 213 storres
                break
310 213 storres
            resultantsComputationTime   = cputime()
311 213 storres
            currentResultantI = \
312 213 storres
                slz_resultant(polyPair[0],
313 213 storres
                              polyPair[1],
314 213 storres
                              t)
315 213 storres
            resultantsComputationsCount    += 1
316 213 storres
            if currentResultantI is None:
317 213 storres
                resultantsComputationsFullTime +=  \
318 213 storres
                    cputime(resultantsComputationTime)
319 213 storres
                print "Nul resultant"
320 213 storres
                continue # Next polyPair.
321 213 storres
            currentResultantT = \
322 213 storres
                slz_resultant(polyPair[0],
323 213 storres
                              polyPair[1],
324 213 storres
                              i)
325 213 storres
            resultantsComputationsFullTime += cputime(resultantsComputationTime)
326 213 storres
            resultantsComputationsCount    += 1
327 213 storres
            if currentResultantT is None:
328 213 storres
                print "Nul resultant"
329 213 storres
                continue # Next polyPair.
330 213 storres
            else:
331 213 storres
                hasNonNullResultant = True
332 213 storres
            #### We have a non null resultants pair. From now on, whatever the
333 213 storres
            #    root search yields, no extra root search is necessary.
334 213 storres
            #### A constant resultant leads to no root. Root search is done.
335 213 storres
            if currentResultantI.degree() < 1:
336 213 storres
                print "Resultant is constant:", currentResultantI
337 213 storres
                break # Next polyPair and should break.
338 213 storres
            if currentResultantT.degree() < 1:
339 213 storres
                print "Resultant is constant:", currentResultantT
340 213 storres
                break # Next polyPair and should break.
341 213 storres
            #### Actual roots computation.
342 213 storres
            rootsComputationTime       = cputime()
343 213 storres
            ##### Compute i roots
344 213 storres
            iRootsList = Zi(currentResultantI).roots()
345 213 storres
            rootsComputationsCount      +=  1
346 213 storres
            if len(iRootsList) == 0:
347 213 storres
                rootsComputationsFullTime   =   cputime(rootsComputationTime)
348 213 storres
                print "No roots in \"i\"."
349 213 storres
                break # No roots in i.
350 213 storres
            tRootsList = Zt(currentResultantT).roots()
351 213 storres
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
352 213 storres
            rootsComputationsCount      +=  1
353 213 storres
            if len(tRootsList) == 0:
354 213 storres
                print "No roots in \"t\"."
355 213 storres
                break # No roots in i.
356 213 storres
            ##### For each iRoot, get a tRoot and check against the polynomials.
357 213 storres
            for iRoot in iRootsList:
358 213 storres
                ####### Roots returned by roots() are (value, multiplicity)
359 213 storres
                #       tuples.
360 213 storres
                #print "iRoot:", iRoot
361 213 storres
                for tRoot in tRootsList:
362 213 storres
                ###### Use the tRoot against each polynomial, alternatively.
363 213 storres
                    if polyPair[0](iRoot[0],tRoot[0]) != 0:
364 213 storres
                        continue
365 213 storres
                    if polyPair[1](iRoot[0],tRoot[0]) != 0:
366 213 storres
                        continue
367 213 storres
                    rootsSet.add((iRoot[0], tRoot[0]))
368 213 storres
            # End of roots computation.
369 213 storres
        # End loop for polyPair in polyParsList.  Will break at next iteration.
370 213 storres
        # since a non null resultant was found.
371 213 storres
        #### Prepare for results for the current interval..
372 213 storres
        intervalResultsList = []
373 213 storres
        intervalResultsList.append((lb, ub))
374 213 storres
        #### Check roots.
375 213 storres
        rootsResultsList = []
376 213 storres
        for root in rootsSet:
377 213 storres
            specificRootResultsList = []
378 213 storres
            failingBounds = []
379 213 storres
            intIntPdivN = intIntP(root[0], root[1]) / N
380 213 storres
            if int(intIntPdivN) != intIntPdivN:
381 213 storres
                continue # Next root
382 213 storres
            # Root qualifies for modular equation, test it for hardness to round.
383 213 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + root[0]) / toIntegerFactor)
384 213 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
385 213 storres
            #print scalingFunction
386 213 storres
            scaledHardToRoundCaseAsFloat = \
387 213 storres
                scalingFunction(hardToRoundCaseAsFloat)
388 213 storres
            print "Candidate HTRNc at x =", \
389 213 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
390 213 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
391 213 storres
                           function,
392 213 storres
                           2^-(targetHardnessToRound),
393 213 storres
                           RRR):
394 213 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
395 213 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
396 213 storres
                    print "Found in interval."
397 213 storres
                else:
398 213 storres
                    print "Found out of interval."
399 213 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
400 213 storres
                # Check the root is in the bounds
401 213 storres
                if abs(root[0]) > iBound or abs(root[1]) > tBound:
402 213 storres
                    print "Root", root, "is out of bounds for modular equation."
403 213 storres
                    if abs(root[0]) > iBound:
404 213 storres
                        print "root[0]:", root[0]
405 213 storres
                        print "i bound:", iBound
406 213 storres
                        failingBounds.append('i')
407 213 storres
                        failingBounds.append(root[0])
408 213 storres
                        failingBounds.append(iBound)
409 213 storres
                    if abs(root[1]) > tBound:
410 213 storres
                        print "root[1]:", root[1]
411 213 storres
                        print "t bound:", tBound
412 213 storres
                        failingBounds.append('t')
413 213 storres
                        failingBounds.append(root[1])
414 213 storres
                        failingBounds.append(tBound)
415 213 storres
                if len(failingBounds) > 0:
416 213 storres
                    specificRootResultsList.append(failingBounds)
417 213 storres
            else: # From slz_is_htrn...
418 213 storres
                print "is not an HTRN case."
419 213 storres
            if len(specificRootResultsList) > 0:
420 213 storres
                rootsResultsList.append(specificRootResultsList)
421 213 storres
        if len(rootsResultsList) > 0:
422 213 storres
            intervalResultsList.append(rootsResultsList)
423 213 storres
        ### Check if a non null resultant was found. If not shrink the interval.
424 213 storres
        if not hasNonNullResultant:
425 213 storres
            print "Only null resultants for this reduction, shrinking interval."
426 213 storres
            resultCondFailed      =  True
427 213 storres
            resultCondFailedCount += 1
428 213 storres
            ### Shrink interval for next iteration.
429 213 storres
            ub = lb + bw * onlyNullResultantsShrink
430 213 storres
            if ub > sdub:
431 213 storres
                ub = sdub
432 213 storres
            nbw = 0
433 213 storres
            continue
434 213 storres
        #### An intervalResultsList has at least the bounds.
435 213 storres
        globalResultsList.append(intervalResultsList)
436 213 storres
        #### Compute an incremented width for next upper bound, only
437 213 storres
        #    if not Coppersmith condition nor resultant condition
438 213 storres
        #    failed at the previous run.
439 213 storres
        if not coppCondFailed and not resultCondFailed:
440 213 storres
            nbw = noErrorIntervalStretch * bw
441 213 storres
        else:
442 213 storres
            nbw = bw
443 213 storres
        ##### Reset the failure flags. They will be raised
444 213 storres
        #     again if needed.
445 213 storres
        coppCondFailed   = False
446 213 storres
        resultCondFailed = False
447 213 storres
        #### For next iteration (at end of loop)
448 213 storres
        #print "nbw:", nbw
449 213 storres
        lb  = ub
450 213 storres
        ub += nbw
451 213 storres
        if ub > sdub:
452 213 storres
            ub = sdub
453 213 storres
        print
454 213 storres
    # End while True
455 213 storres
    ## Main loop just ended.
456 213 storres
    globalWallTime = walltime(wallTimeStart)
457 213 storres
    globalCpuTime  = cputime(cpuTimeStart)
458 213 storres
    ## Output results
459 213 storres
    print ; print "Intervals and HTRNs" ; print
460 213 storres
    for intervalResultsList in globalResultsList:
461 222 storres
        intervalResultString = "[" + str(intervalResultsList[0][0]) +\
462 222 storres
                               "," + str(intervalResultsList[0][1])  + "]"
463 222 storres
        print intervalResultString,
464 213 storres
        if len(intervalResultsList) > 1:
465 213 storres
            rootsResultsList = intervalResultsList[1]
466 222 storres
            specificRootResultIndex = 0
467 213 storres
            for specificRootResultsList in rootsResultsList:
468 222 storres
                if specificRootResultIndex == 0:
469 222 storres
                    print "\t", specificRootResultsList[0],
470 222 storres
                else:
471 222 storres
                    print " " * len(intervalResultString), "\t", \
472 222 storres
                          specificRootResultsList[0],
473 213 storres
                if len(specificRootResultsList) > 1:
474 222 storres
                    print specificRootResultsList[1]
475 222 storres
                specificRootResultIndex += 1
476 213 storres
        print ; print
477 213 storres
    #print globalResultsList
478 213 storres
    #
479 213 storres
    print "Timers and counters"
480 213 storres
    print
481 213 storres
    print "Number of iterations:", iterCount
482 213 storres
    print "Taylor condition failures:", taylCondFailedCount
483 213 storres
    print "Coppersmith condition failures:", coppCondFailedCount
484 213 storres
    print "Resultant condition failures:", resultCondFailedCount
485 213 storres
    print "Iterations count: ", iterCount
486 213 storres
    print "Number of intervals:", len(globalResultsList)
487 213 storres
    print "Number of basis constructions:", basisConstructionsCount
488 213 storres
    print "Total CPU time spent in basis constructions:", \
489 213 storres
        basisConstructionsFullTime
490 213 storres
    if basisConstructionsCount != 0:
491 213 storres
        print "Average basis construction CPU time:", \
492 213 storres
            basisConstructionsFullTime/basisConstructionsCount
493 213 storres
    print "Number of reductions:", reductionsCount
494 213 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
495 213 storres
    if reductionsCount != 0:
496 213 storres
        print "Average reduction CPU time:", \
497 213 storres
            reductionsFullTime/reductionsCount
498 213 storres
    print "Number of resultants computation rounds:", \
499 213 storres
        resultantsComputationsCount
500 213 storres
    print "Total CPU time spent in resultants computation rounds:", \
501 213 storres
        resultantsComputationsFullTime
502 213 storres
    if resultantsComputationsCount != 0:
503 213 storres
        print "Average resultants computation round CPU time:", \
504 213 storres
            resultantsComputationsFullTime/resultantsComputationsCount
505 213 storres
    print "Number of root finding rounds:", rootsComputationsCount
506 213 storres
    print "Total CPU time spent in roots finding rounds:", \
507 213 storres
        rootsComputationsFullTime
508 213 storres
    if rootsComputationsCount != 0:
509 213 storres
        print "Average roots finding round CPU time:", \
510 213 storres
            rootsComputationsFullTime/rootsComputationsCount
511 213 storres
    print "Global Wall time:", globalWallTime
512 213 storres
    print "Global CPU time:", globalCpuTime
513 213 storres
    ## Output counters
514 213 storres
# End srs_compute_lattice_volume
515 213 storres
516 213 storres
"""
517 194 storres
SLZ runtime function.
518 194 storres
"""
519 194 storres
520 194 storres
def srs_run_SLZ_v01(inputFunction,
521 194 storres
                    inputLowerBound,
522 194 storres
                    inputUpperBound,
523 194 storres
                    alpha,
524 194 storres
                    degree,
525 194 storres
                    precision,
526 194 storres
                    emin,
527 194 storres
                    emax,
528 194 storres
                    targetHardnessToRound,
529 194 storres
                    debug = False):
530 194 storres
531 194 storres
    if debug:
532 194 storres
        print "Function                :", inputFunction
533 194 storres
        print "Lower bound             :", inputLowerBound
534 194 storres
        print "Upper bounds            :", inputUpperBound
535 194 storres
        print "Alpha                   :", alpha
536 194 storres
        print "Degree                  :", degree
537 194 storres
        print "Precision               :", precision
538 194 storres
        print "Emin                    :", emin
539 194 storres
        print "Emax                    :", emax
540 194 storres
        print "Target hardness-to-round:", targetHardnessToRound
541 194 storres
        print
542 194 storres
    ## Important constants.
543 194 storres
    ### Stretch the interval if no error happens.
544 194 storres
    noErrorIntervalStretch = 1 + 2^(-5)
545 194 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
546 194 storres
    #   by the following factor.
547 194 storres
    noCoppersmithIntervalShrink = 1/2
548 194 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
549 194 storres
    #   shrink the interval by the following factor.
550 194 storres
    oneCoppersmithIntervalShrink = 3/4
551 194 storres
    #### If only null resultants are found, shrink the interval by the
552 194 storres
    #    following factor.
553 194 storres
    onlyNullResultantsShrink     = 3/4
554 194 storres
    ## Structures.
555 194 storres
    RRR         = RealField(precision)
556 194 storres
    RRIF        = RealIntervalField(precision)
557 194 storres
    ## Converting input bound into the "right" field.
558 194 storres
    lowerBound = RRR(inputLowerBound)
559 194 storres
    upperBound = RRR(inputUpperBound)
560 194 storres
    ## Before going any further, check domain and image binade conditions.
561 194 storres
    print inputFunction(1).n()
562 206 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
563 206 storres
    if output is None:
564 206 storres
        print "Invalid domain/image binades. Domain:",\
565 206 storres
        lowerBound, upperBound, "Images:", \
566 206 storres
        inputFunction(lowerBound), inputFunction(upperBound)
567 206 storres
        raise Exception("Invalid domain/image binades.")
568 206 storres
    lb = output[0] ; ub = output[1]
569 206 storres
    if lb is None or lb != lowerBound or ub != upperBound:
570 194 storres
        print "lb:", lb, " - ub:", ub
571 194 storres
        print "Invalid domain/image binades. Domain:",\
572 194 storres
        lowerBound, upperBound, "Images:", \
573 194 storres
        inputFunction(lowerBound), inputFunction(upperBound)
574 194 storres
        raise Exception("Invalid domain/image binades.")
575 194 storres
    #
576 194 storres
    ## Progam initialization
577 194 storres
    ### Approximation polynomial accuracy and hardness to round.
578 194 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
579 194 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
580 194 storres
    ### Significand to integer conversion ratio.
581 194 storres
    toIntegerFactor           = 2^(precision-1)
582 194 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
583 194 storres
    ### Variables and rings for polynomials and root searching.
584 194 storres
    i=var('i')
585 194 storres
    t=var('t')
586 194 storres
    inputFunctionVariable = inputFunction.variables()[0]
587 194 storres
    function = inputFunction.subs({inputFunctionVariable:i})
588 194 storres
    #  Polynomial Rings over the integers, for root finding.
589 194 storres
    Zi = ZZ[i]
590 194 storres
    Zt = ZZ[t]
591 194 storres
    Zit = ZZ[i,t]
592 194 storres
    ## Number of iterations limit.
593 194 storres
    maxIter = 100000
594 194 storres
    #
595 231 storres
    ## Set the variable name in Sollya.
596 231 storres
    pobyso_name_free_variable_sa_so(str(function.variables()[0]))
597 194 storres
    ## Compute the scaled function and the degree, in their Sollya version
598 194 storres
    #  once for all.
599 194 storres
    (scaledf, sdlb, sdub, silb, siub) = \
600 194 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
601 194 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
602 194 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
603 194 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
604 194 storres
    #
605 194 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
606 194 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
607 194 storres
    (unscalingFunction, scalingFunction) = \
608 194 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
609 194 storres
    #print scalingFunction, unscalingFunction
610 194 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
611 194 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
612 194 storres
    if internalSollyaPrec < 192:
613 194 storres
        internalSollyaPrec = 192
614 194 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
615 194 storres
    print "Sollya internal precision:", internalSollyaPrec
616 194 storres
    ## Some variables.
617 194 storres
    ### General variables
618 194 storres
    lb                  = sdlb
619 194 storres
    ub                  = sdub
620 194 storres
    nbw                 = 0
621 194 storres
    intervalUlp         = ub.ulp()
622 194 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
623 194 storres
    ic                  = 0
624 194 storres
    icAsInt             = 0    # Set from ic.
625 194 storres
    solutionsSet        = set()
626 194 storres
    tsErrorWidth        = []
627 194 storres
    csErrorVectors      = []
628 194 storres
    csVectorsResultants = []
629 194 storres
    floatP              = 0  # Taylor polynomial.
630 194 storres
    floatPcv            = 0  # Ditto with variable change.
631 194 storres
    intvl               = "" # Taylor interval
632 194 storres
    terr                = 0  # Taylor error.
633 194 storres
    iterCount = 0
634 194 storres
    htrnSet = set()
635 194 storres
    ### Timers and counters.
636 194 storres
    wallTimeStart                   = 0
637 194 storres
    cpuTimeStart                    = 0
638 194 storres
    taylCondFailedCount             = 0
639 194 storres
    coppCondFailedCount             = 0
640 194 storres
    resultCondFailedCount           = 0
641 194 storres
    coppCondFailed                  = False
642 194 storres
    resultCondFailed                = False
643 194 storres
    globalResultsList               = []
644 194 storres
    basisConstructionsCount         = 0
645 194 storres
    basisConstructionsFullTime      = 0
646 194 storres
    basisConstructionTime           = 0
647 194 storres
    reductionsCount                 = 0
648 194 storres
    reductionsFullTime              = 0
649 194 storres
    reductionTime                   = 0
650 194 storres
    resultantsComputationsCount     = 0
651 194 storres
    resultantsComputationsFullTime  = 0
652 194 storres
    resultantsComputationTime       = 0
653 194 storres
    rootsComputationsCount          = 0
654 194 storres
    rootsComputationsFullTime       = 0
655 194 storres
    rootsComputationTime            = 0
656 194 storres
    print
657 194 storres
    ## Global times are started here.
658 194 storres
    wallTimeStart                   = walltime()
659 194 storres
    cpuTimeStart                    = cputime()
660 194 storres
    ## Main loop.
661 194 storres
    while True:
662 194 storres
        if lb >= sdub:
663 194 storres
            print "Lower bound reached upper bound."
664 194 storres
            break
665 194 storres
        if iterCount == maxIter:
666 194 storres
            print "Reached maxIter. Aborting"
667 194 storres
            break
668 194 storres
        iterCount += 1
669 194 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
670 194 storres
            "log2(numbers)."
671 194 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
672 194 storres
        prceSo = slz_compute_polynomial_and_interval(scaledfSo,
673 194 storres
                                                     degreeSo,
674 194 storres
                                                     lb,
675 194 storres
                                                     ub,
676 194 storres
                                                     polyApproxAccur)
677 194 storres
        ### Convert back the data into Sage space.
678 194 storres
        (floatP, floatPcv, intvl, ic, terr) = \
679 194 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
680 194 storres
                                                 prceSo[1], prceSo[2],
681 194 storres
                                                 prceSo[3]))
682 194 storres
        intvl = RRIF(intvl)
683 194 storres
        ## Clean-up Sollya stuff.
684 194 storres
        for elem in prceSo:
685 194 storres
            sollya_lib_clear_obj(elem)
686 194 storres
        #print  floatP, floatPcv, intvl, ic, terr
687 194 storres
        #print floatP
688 194 storres
        #print intvl.endpoints()[0].n(), \
689 194 storres
        #      ic.n(),
690 194 storres
        #intvl.endpoints()[1].n()
691 194 storres
        ### Check returned data.
692 194 storres
        #### Is approximation error OK?
693 194 storres
        if terr > polyApproxAccur:
694 194 storres
            exceptionErrorMess  = \
695 194 storres
                "Approximation failed - computed error:" + \
696 194 storres
                str(terr) + " - target error: "
697 194 storres
            exceptionErrorMess += \
698 194 storres
                str(polyApproxAccur) + ". Aborting!"
699 194 storres
            raise Exception(exceptionErrorMess)
700 194 storres
        #### Is lower bound OK?
701 194 storres
        if lb != intvl.endpoints()[0]:
702 194 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
703 194 storres
                               str(lb) + ". Aborting!"
704 194 storres
            raise Exception(exceptionErrorMess)
705 194 storres
        #### Set upper bound.
706 194 storres
        if ub > intvl.endpoints()[1]:
707 194 storres
            ub = intvl.endpoints()[1]
708 194 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
709 194 storres
            "log2(numbers)."
710 194 storres
            taylCondFailedCount += 1
711 194 storres
        #### Is interval not degenerate?
712 194 storres
        if lb >= ub:
713 194 storres
            exceptionErrorMess = "Degenerate interval: " + \
714 194 storres
                                "lowerBound(" + str(lb) +\
715 194 storres
                                ")>= upperBound(" + str(ub) + \
716 194 storres
                                "). Aborting!"
717 194 storres
            raise Exception(exceptionErrorMess)
718 194 storres
        #### Is interval center ok?
719 194 storres
        if ic <= lb or ic >= ub:
720 194 storres
            exceptionErrorMess =  "Invalid interval center for " + \
721 194 storres
                                str(lb) + ',' + str(ic) + ',' +  \
722 194 storres
                                str(ub) + ". Aborting!"
723 194 storres
            raise Exception(exceptionErrorMess)
724 194 storres
        ##### Current interval width and reset future interval width.
725 194 storres
        bw = ub - lb
726 194 storres
        nbw = 0
727 194 storres
        icAsInt = int(ic * toIntegerFactor)
728 194 storres
        #### The following ratio is always >= 1. In case we may want to
729 194 storres
        #  enlarge the interval
730 194 storres
        curTaylErrRat = polyApproxAccur / terr
731 194 storres
        ## Make the  integral transformations.
732 194 storres
        ### First for interval center and bounds.
733 194 storres
        intIc = int(ic * toIntegerFactor)
734 194 storres
        intLb = int(lb * toIntegerFactor) - intIc
735 194 storres
        intUb = int(ub * toIntegerFactor) - intIc
736 194 storres
        #
737 194 storres
        #### For polynomials
738 194 storres
        basisConstructionTime         = cputime()
739 194 storres
        ##### To a polynomial with rational coefficients with rational arguments
740 194 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
741 194 storres
        ##### To a polynomial with rational coefficients with integer arguments
742 194 storres
        ratIntP = \
743 194 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
744 194 storres
        #####  Ultimately a polynomial with integer coefficients with integer
745 194 storres
        #      arguments.
746 194 storres
        coppersmithTuple = \
747 194 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
748 194 storres
                                                        precision,
749 194 storres
                                                        targetHardnessToRound,
750 194 storres
                                                        i, t)
751 194 storres
        #### Recover Coppersmith information.
752 194 storres
        intIntP = coppersmithTuple[0]
753 194 storres
        N = coppersmithTuple[1]
754 194 storres
        nAtAlpha = N^alpha
755 194 storres
        tBound = coppersmithTuple[2]
756 194 storres
        leastCommonMultiple = coppersmithTuple[3]
757 194 storres
        iBound = max(abs(intLb),abs(intUb))
758 194 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
759 194 storres
        basisConstructionsCount           += 1
760 194 storres
        reductionTime                     = cputime()
761 194 storres
        # Compute the reduced polynomials.
762 194 storres
        ccReducedPolynomialsList =  \
763 212 storres
                slz_compute_coppersmith_reduced_polynomials(intIntP,
764 212 storres
                                                            alpha,
765 212 storres
                                                            N,
766 212 storres
                                                            iBound,
767 212 storres
                                                            tBound)
768 194 storres
        if ccReducedPolynomialsList is None:
769 194 storres
            raise Exception("Reduction failed.")
770 194 storres
        reductionsFullTime    += cputime(reductionTime)
771 194 storres
        reductionsCount       += 1
772 194 storres
        if len(ccReducedPolynomialsList) < 2:
773 194 storres
            print "Nothing to form resultants with."
774 194 storres
            print
775 194 storres
            coppCondFailedCount += 1
776 194 storres
            coppCondFailed = True
777 194 storres
            ##### Apply a different shrink factor according to
778 194 storres
            #  the number of compliant polynomials.
779 194 storres
            if len(ccReducedPolynomialsList) == 0:
780 194 storres
                ub = lb + bw * noCoppersmithIntervalShrink
781 194 storres
            else: # At least one compliant polynomial.
782 194 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
783 194 storres
            if ub > sdub:
784 194 storres
                ub = sdub
785 194 storres
            if lb == ub:
786 194 storres
                raise Exception("Cant shrink interval \
787 194 storres
                anymore to get Coppersmith condition.")
788 194 storres
            nbw = 0
789 194 storres
            continue
790 194 storres
        #### We have at least two polynomials.
791 194 storres
        #    Let us try to compute resultants.
792 194 storres
        resultantsComputationTime      = cputime()
793 194 storres
        resultantsInTTuplesList = []
794 194 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
795 194 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
796 194 storres
                                         len(ccReducedPolynomialsList)):
797 194 storres
                resultantTuple = \
798 194 storres
                slz_resultant_tuple(ccReducedPolynomialsList[polyOuterIndex],
799 194 storres
                                ccReducedPolynomialsList[polyInnerIndex],
800 194 storres
                                t)
801 194 storres
                if len(resultantTuple) > 2:
802 194 storres
                    #print resultantTuple[2]
803 194 storres
                    resultantsInTTuplesList.append(resultantTuple)
804 194 storres
                else:
805 194 storres
                    print "No non nul resultant"
806 194 storres
        print len(resultantsInTTuplesList), "resultant(s) in t tuple(s) created."
807 194 storres
        resultantsComputationsFullTime += cputime(resultantsComputationTime)
808 194 storres
        resultantsComputationsCount    += 1
809 194 storres
        if len(resultantsInTTuplesList) == 0:
810 194 storres
            print "Only null resultants, shrinking interval."
811 194 storres
            resultCondFailed      =  True
812 194 storres
            resultCondFailedCount += 1
813 194 storres
            ### Shrink interval for next iteration.
814 194 storres
            ub = lb + bw * onlyNullResultantsShrink
815 194 storres
            if ub > sdub:
816 194 storres
                ub = sdub
817 194 storres
            nbw = 0
818 194 storres
            continue
819 194 storres
        #### Compute roots.
820 194 storres
        rootsComputationTime       = cputime()
821 194 storres
        reducedPolynomialsRootsSet = set()
822 194 storres
        ##### Solve in the second variable since resultants are in the first
823 194 storres
        #     variable.
824 194 storres
        for resultantInTTuple in resultantsInTTuplesList:
825 194 storres
            currentResultant = resultantInTTuple[2]
826 194 storres
            ##### If the resultant degree is not at least 1, there are no roots.
827 194 storres
            if currentResultant.degree() < 1:
828 194 storres
                print "Resultant is constant:", currentResultant
829 194 storres
                continue # Next resultantInTTuple
830 194 storres
            ##### Compute i roots
831 194 storres
            iRootsList = Zi(currentResultant).roots()
832 194 storres
            ##### For each iRoot, compute the corresponding tRoots and check
833 194 storres
            #     them in the input polynomial.
834 194 storres
            for iRoot in iRootsList:
835 194 storres
                ####### Roots returned by roots() are (value, multiplicity)
836 194 storres
                #       tuples.
837 194 storres
                #print "iRoot:", iRoot
838 194 storres
                ###### Use the tRoot against each polynomial, alternatively.
839 194 storres
                for indexInTuple in range(0,2):
840 194 storres
                    currentPolynomial = resultantInTTuple[indexInTuple]
841 194 storres
                    ####### If the polynomial is univariate, just drop it.
842 194 storres
                    if len(currentPolynomial.variables()) < 2:
843 194 storres
                        print "    Current polynomial is not in two variables."
844 194 storres
                        continue # Next indexInTuple
845 194 storres
                    tRootsList = \
846 194 storres
                        Zt(currentPolynomial.subs({currentPolynomial.variables()[0]:iRoot[0]})).roots()
847 194 storres
                    ####### The tRootsList can be empty, hence the test.
848 194 storres
                    if len(tRootsList) == 0:
849 194 storres
                        print "    No t root."
850 194 storres
                        continue # Next indexInTuple
851 194 storres
                    for tRoot in tRootsList:
852 194 storres
                        reducedPolynomialsRootsSet.add((iRoot[0], tRoot[0]))
853 194 storres
        # End of roots computation
854 194 storres
        rootsComputationsFullTime   =   cputime(rootsComputationTime)
855 194 storres
        rootsComputationsCount      +=  1
856 194 storres
        ##### Prepare for results.
857 194 storres
        intervalResultsList = []
858 194 storres
        intervalResultsList.append((lb, ub))
859 194 storres
        #### Check roots.
860 194 storres
        rootsResultsList = []
861 194 storres
        for root in reducedPolynomialsRootsSet:
862 194 storres
            specificRootResultsList = []
863 194 storres
            failingBounds = []
864 194 storres
            intIntPdivN = intIntP(root[0], root[1]) / N
865 194 storres
            if int(intIntPdivN) != intIntPdivN:
866 194 storres
                continue # Next root
867 194 storres
            # Root qualifies for modular equation, test it for hardness to round.
868 194 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + root[0]) / toIntegerFactor)
869 194 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
870 194 storres
            #print scalingFunction
871 194 storres
            scaledHardToRoundCaseAsFloat = \
872 194 storres
                scalingFunction(hardToRoundCaseAsFloat)
873 194 storres
            print "Candidate HTRNc at x =", \
874 194 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
875 194 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
876 194 storres
                           function,
877 194 storres
                           2^-(targetHardnessToRound),
878 194 storres
                           RRR):
879 194 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
880 194 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
881 194 storres
                    print "Found in interval."
882 194 storres
                else:
883 194 storres
                    print "Found out of interval."
884 194 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
885 194 storres
                # Check the root is in the bounds
886 194 storres
                if abs(root[0]) > iBound or abs(root[1]) > tBound:
887 194 storres
                    print "Root", root, "is out of bounds."
888 194 storres
                    if abs(root[0]) > iBound:
889 194 storres
                        print "root[0]:", root[0]
890 194 storres
                        print "i bound:", iBound
891 194 storres
                        failingBounds.append('i')
892 194 storres
                        failingBounds.append(root[0])
893 194 storres
                        failingBounds.append(iBound)
894 194 storres
                    if abs(root[1]) > tBound:
895 194 storres
                        print "root[1]:", root[1]
896 194 storres
                        print "t bound:", tBound
897 194 storres
                        failingBounds.append('t')
898 194 storres
                        failingBounds.append(root[1])
899 194 storres
                        failingBounds.append(tBound)
900 194 storres
                if len(failingBounds) > 0:
901 194 storres
                    specificRootResultsList.append(failingBounds)
902 194 storres
            else: # From slz_is_htrn...
903 194 storres
                print "is not an HTRN case."
904 194 storres
            if len(specificRootResultsList) > 0:
905 194 storres
                rootsResultsList.append(specificRootResultsList)
906 194 storres
        if len(rootsResultsList) > 0:
907 194 storres
            intervalResultsList.append(rootsResultsList)
908 194 storres
        #### An intervalResultsList has at least the bounds.
909 194 storres
        globalResultsList.append(intervalResultsList)
910 194 storres
        #### Compute an incremented width for next upper bound, only
911 194 storres
        #    if not Coppersmith condition nor resultant condition
912 194 storres
        #    failed at the previous run.
913 194 storres
        if not coppCondFailed and not resultCondFailed:
914 194 storres
            nbw = noErrorIntervalStretch * bw
915 194 storres
        else:
916 194 storres
            nbw = bw
917 194 storres
        ##### Reset the failure flags. They will be raised
918 194 storres
        #     again if needed.
919 194 storres
        coppCondFailed   = False
920 194 storres
        resultCondFailed = False
921 194 storres
        #### For next iteration (at end of loop)
922 194 storres
        #print "nbw:", nbw
923 194 storres
        lb  = ub
924 194 storres
        ub += nbw
925 194 storres
        if ub > sdub:
926 194 storres
            ub = sdub
927 194 storres
        print
928 194 storres
    # End while True
929 194 storres
    ## Main loop just ended.
930 194 storres
    globalWallTime = walltime(wallTimeStart)
931 194 storres
    globalCpuTime  = cputime(cpuTimeStart)
932 194 storres
    ## Output results
933 194 storres
    print ; print "Intervals and HTRNs" ; print
934 194 storres
    for intervalResultsList in globalResultsList:
935 222 storres
        intervalResultString = "[" + str(intervalResultsList[0][0]) +\
936 222 storres
                               "," + str(intervalResultsList[0][1])  + "]"
937 222 storres
        print intervalResultString,
938 194 storres
        if len(intervalResultsList) > 1:
939 194 storres
            rootsResultsList = intervalResultsList[1]
940 222 storres
            specificRootResultIndex = 0
941 194 storres
            for specificRootResultsList in rootsResultsList:
942 222 storres
                if specificRootResultIndex == 0:
943 222 storres
                    print "\t", specificRootResultsList[0],
944 222 storres
                else:
945 222 storres
                    print " " * len(intervalResultString), "\t", \
946 222 storres
                          specificRootResultsList[0],
947 194 storres
                if len(specificRootResultsList) > 1:
948 222 storres
                    print specificRootResultsList[1]
949 222 storres
                specificRootResultIndex += 1
950 194 storres
        print ; print
951 194 storres
    #print globalResultsList
952 194 storres
    #
953 194 storres
    print "Timers and counters"
954 194 storres
    print
955 194 storres
    print "Number of iterations:", iterCount
956 194 storres
    print "Taylor condition failures:", taylCondFailedCount
957 194 storres
    print "Coppersmith condition failures:", coppCondFailedCount
958 194 storres
    print "Resultant condition failures:", resultCondFailedCount
959 194 storres
    print "Iterations count: ", iterCount
960 194 storres
    print "Number of intervals:", len(globalResultsList)
961 194 storres
    print "Number of basis constructions:", basisConstructionsCount
962 194 storres
    print "Total CPU time spent in basis constructions:", \
963 194 storres
        basisConstructionsFullTime
964 194 storres
    if basisConstructionsCount != 0:
965 194 storres
        print "Average basis construction CPU time:", \
966 194 storres
            basisConstructionsFullTime/basisConstructionsCount
967 194 storres
    print "Number of reductions:", reductionsCount
968 194 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
969 194 storres
    if reductionsCount != 0:
970 194 storres
        print "Average reduction CPU time:", \
971 194 storres
            reductionsFullTime/reductionsCount
972 194 storres
    print "Number of resultants computation rounds:", \
973 194 storres
        resultantsComputationsCount
974 194 storres
    print "Total CPU time spent in resultants computation rounds:", \
975 194 storres
        resultantsComputationsFullTime
976 194 storres
    if resultantsComputationsCount != 0:
977 194 storres
        print "Average resultants computation round CPU time:", \
978 194 storres
            resultantsComputationsFullTime/resultantsComputationsCount
979 194 storres
    print "Number of root finding rounds:", rootsComputationsCount
980 194 storres
    print "Total CPU time spent in roots finding rounds:", \
981 194 storres
        rootsComputationsFullTime
982 194 storres
    if rootsComputationsCount != 0:
983 194 storres
        print "Average roots finding round CPU time:", \
984 194 storres
            rootsComputationsFullTime/rootsComputationsCount
985 194 storres
    print "Global Wall time:", globalWallTime
986 194 storres
    print "Global CPU time:", globalCpuTime
987 194 storres
    ## Output counters
988 194 storres
# End srs_runSLZ-v01
989 194 storres
990 194 storres
def srs_run_SLZ_v02(inputFunction,
991 194 storres
                    inputLowerBound,
992 194 storres
                    inputUpperBound,
993 194 storres
                    alpha,
994 194 storres
                    degree,
995 194 storres
                    precision,
996 194 storres
                    emin,
997 194 storres
                    emax,
998 194 storres
                    targetHardnessToRound,
999 194 storres
                    debug = False):
1000 194 storres
    """
1001 194 storres
    Changes from V1:
1002 194 storres
        1- check for roots as soon as a resultant is computed;
1003 194 storres
        2- once a non null resultant is found, check for roots;
1004 194 storres
        3- constant resultant == no root.
1005 194 storres
    """
1006 194 storres
1007 194 storres
    if debug:
1008 194 storres
        print "Function                :", inputFunction
1009 194 storres
        print "Lower bound             :", inputLowerBound
1010 194 storres
        print "Upper bounds            :", inputUpperBound
1011 194 storres
        print "Alpha                   :", alpha
1012 194 storres
        print "Degree                  :", degree
1013 194 storres
        print "Precision               :", precision
1014 194 storres
        print "Emin                    :", emin
1015 194 storres
        print "Emax                    :", emax
1016 194 storres
        print "Target hardness-to-round:", targetHardnessToRound
1017 194 storres
        print
1018 194 storres
    ## Important constants.
1019 194 storres
    ### Stretch the interval if no error happens.
1020 194 storres
    noErrorIntervalStretch = 1 + 2^(-5)
1021 194 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
1022 194 storres
    #   by the following factor.
1023 194 storres
    noCoppersmithIntervalShrink = 1/2
1024 194 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
1025 194 storres
    #   shrink the interval by the following factor.
1026 194 storres
    oneCoppersmithIntervalShrink = 3/4
1027 194 storres
    #### If only null resultants are found, shrink the interval by the
1028 194 storres
    #    following factor.
1029 194 storres
    onlyNullResultantsShrink     = 3/4
1030 194 storres
    ## Structures.
1031 194 storres
    RRR         = RealField(precision)
1032 194 storres
    RRIF        = RealIntervalField(precision)
1033 194 storres
    ## Converting input bound into the "right" field.
1034 194 storres
    lowerBound = RRR(inputLowerBound)
1035 194 storres
    upperBound = RRR(inputUpperBound)
1036 194 storres
    ## Before going any further, check domain and image binade conditions.
1037 194 storres
    print inputFunction(1).n()
1038 206 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
1039 206 storres
    if output is None:
1040 206 storres
        print "Invalid domain/image binades. Domain:",\
1041 206 storres
        lowerBound, upperBound, "Images:", \
1042 206 storres
        inputFunction(lowerBound), inputFunction(upperBound)
1043 206 storres
        raise Exception("Invalid domain/image binades.")
1044 206 storres
    lb = output[0] ; ub = output[1]
1045 194 storres
    if lb != lowerBound or ub != upperBound:
1046 194 storres
        print "lb:", lb, " - ub:", ub
1047 194 storres
        print "Invalid domain/image binades. Domain:",\
1048 194 storres
        lowerBound, upperBound, "Images:", \
1049 194 storres
        inputFunction(lowerBound), inputFunction(upperBound)
1050 194 storres
        raise Exception("Invalid domain/image binades.")
1051 194 storres
    #
1052 194 storres
    ## Progam initialization
1053 194 storres
    ### Approximation polynomial accuracy and hardness to round.
1054 194 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
1055 194 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
1056 194 storres
    ### Significand to integer conversion ratio.
1057 194 storres
    toIntegerFactor           = 2^(precision-1)
1058 194 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
1059 194 storres
    ### Variables and rings for polynomials and root searching.
1060 194 storres
    i=var('i')
1061 194 storres
    t=var('t')
1062 194 storres
    inputFunctionVariable = inputFunction.variables()[0]
1063 194 storres
    function = inputFunction.subs({inputFunctionVariable:i})
1064 194 storres
    #  Polynomial Rings over the integers, for root finding.
1065 194 storres
    Zi = ZZ[i]
1066 194 storres
    Zt = ZZ[t]
1067 194 storres
    Zit = ZZ[i,t]
1068 194 storres
    ## Number of iterations limit.
1069 194 storres
    maxIter = 100000
1070 194 storres
    #
1071 231 storres
    ## Set the variable name in Sollya.
1072 231 storres
    pobyso_name_free_variable_sa_so(str(function.variables()[0]))
1073 194 storres
    ## Compute the scaled function and the degree, in their Sollya version
1074 194 storres
    #  once for all.
1075 194 storres
    (scaledf, sdlb, sdub, silb, siub) = \
1076 194 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
1077 194 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
1078 194 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
1079 194 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
1080 194 storres
    #
1081 194 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
1082 194 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
1083 194 storres
    (unscalingFunction, scalingFunction) = \
1084 194 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
1085 194 storres
    #print scalingFunction, unscalingFunction
1086 194 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
1087 194 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
1088 194 storres
    if internalSollyaPrec < 192:
1089 194 storres
        internalSollyaPrec = 192
1090 194 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
1091 194 storres
    print "Sollya internal precision:", internalSollyaPrec
1092 194 storres
    ## Some variables.
1093 194 storres
    ### General variables
1094 194 storres
    lb                  = sdlb
1095 194 storres
    ub                  = sdub
1096 194 storres
    nbw                 = 0
1097 194 storres
    intervalUlp         = ub.ulp()
1098 194 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
1099 194 storres
    ic                  = 0
1100 194 storres
    icAsInt             = 0    # Set from ic.
1101 194 storres
    solutionsSet        = set()
1102 194 storres
    tsErrorWidth        = []
1103 194 storres
    csErrorVectors      = []
1104 194 storres
    csVectorsResultants = []
1105 194 storres
    floatP              = 0  # Taylor polynomial.
1106 194 storres
    floatPcv            = 0  # Ditto with variable change.
1107 194 storres
    intvl               = "" # Taylor interval
1108 194 storres
    terr                = 0  # Taylor error.
1109 194 storres
    iterCount = 0
1110 194 storres
    htrnSet = set()
1111 194 storres
    ### Timers and counters.
1112 194 storres
    wallTimeStart                   = 0
1113 194 storres
    cpuTimeStart                    = 0
1114 194 storres
    taylCondFailedCount             = 0
1115 194 storres
    coppCondFailedCount             = 0
1116 194 storres
    resultCondFailedCount           = 0
1117 194 storres
    coppCondFailed                  = False
1118 194 storres
    resultCondFailed                = False
1119 194 storres
    globalResultsList               = []
1120 194 storres
    basisConstructionsCount         = 0
1121 194 storres
    basisConstructionsFullTime      = 0
1122 194 storres
    basisConstructionTime           = 0
1123 194 storres
    reductionsCount                 = 0
1124 194 storres
    reductionsFullTime              = 0
1125 194 storres
    reductionTime                   = 0
1126 194 storres
    resultantsComputationsCount     = 0
1127 194 storres
    resultantsComputationsFullTime  = 0
1128 194 storres
    resultantsComputationTime       = 0
1129 194 storres
    rootsComputationsCount          = 0
1130 194 storres
    rootsComputationsFullTime       = 0
1131 194 storres
    rootsComputationTime            = 0
1132 194 storres
    print
1133 194 storres
    ## Global times are started here.
1134 194 storres
    wallTimeStart                   = walltime()
1135 194 storres
    cpuTimeStart                    = cputime()
1136 194 storres
    ## Main loop.
1137 194 storres
    while True:
1138 194 storres
        if lb >= sdub:
1139 194 storres
            print "Lower bound reached upper bound."
1140 194 storres
            break
1141 194 storres
        if iterCount == maxIter:
1142 194 storres
            print "Reached maxIter. Aborting"
1143 194 storres
            break
1144 194 storres
        iterCount += 1
1145 194 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
1146 194 storres
            "log2(numbers)."
1147 194 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
1148 194 storres
        prceSo = slz_compute_polynomial_and_interval(scaledfSo,
1149 194 storres
                                                     degreeSo,
1150 194 storres
                                                     lb,
1151 194 storres
                                                     ub,
1152 194 storres
                                                     polyApproxAccur)
1153 194 storres
        ### Convert back the data into Sage space.
1154 194 storres
        (floatP, floatPcv, intvl, ic, terr) = \
1155 194 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
1156 194 storres
                                                 prceSo[1], prceSo[2],
1157 194 storres
                                                 prceSo[3]))
1158 194 storres
        intvl = RRIF(intvl)
1159 194 storres
        ## Clean-up Sollya stuff.
1160 194 storres
        for elem in prceSo:
1161 194 storres
            sollya_lib_clear_obj(elem)
1162 194 storres
        #print  floatP, floatPcv, intvl, ic, terr
1163 194 storres
        #print floatP
1164 194 storres
        #print intvl.endpoints()[0].n(), \
1165 194 storres
        #      ic.n(),
1166 194 storres
        #intvl.endpoints()[1].n()
1167 194 storres
        ### Check returned data.
1168 194 storres
        #### Is approximation error OK?
1169 194 storres
        if terr > polyApproxAccur:
1170 194 storres
            exceptionErrorMess  = \
1171 194 storres
                "Approximation failed - computed error:" + \
1172 194 storres
                str(terr) + " - target error: "
1173 194 storres
            exceptionErrorMess += \
1174 194 storres
                str(polyApproxAccur) + ". Aborting!"
1175 194 storres
            raise Exception(exceptionErrorMess)
1176 194 storres
        #### Is lower bound OK?
1177 194 storres
        if lb != intvl.endpoints()[0]:
1178 194 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
1179 194 storres
                               str(lb) + ". Aborting!"
1180 194 storres
            raise Exception(exceptionErrorMess)
1181 194 storres
        #### Set upper bound.
1182 194 storres
        if ub > intvl.endpoints()[1]:
1183 194 storres
            ub = intvl.endpoints()[1]
1184 194 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
1185 194 storres
            "log2(numbers)."
1186 194 storres
            taylCondFailedCount += 1
1187 194 storres
        #### Is interval not degenerate?
1188 194 storres
        if lb >= ub:
1189 194 storres
            exceptionErrorMess = "Degenerate interval: " + \
1190 194 storres
                                "lowerBound(" + str(lb) +\
1191 194 storres
                                ")>= upperBound(" + str(ub) + \
1192 194 storres
                                "). Aborting!"
1193 194 storres
            raise Exception(exceptionErrorMess)
1194 194 storres
        #### Is interval center ok?
1195 194 storres
        if ic <= lb or ic >= ub:
1196 194 storres
            exceptionErrorMess =  "Invalid interval center for " + \
1197 194 storres
                                str(lb) + ',' + str(ic) + ',' +  \
1198 194 storres
                                str(ub) + ". Aborting!"
1199 194 storres
            raise Exception(exceptionErrorMess)
1200 194 storres
        ##### Current interval width and reset future interval width.
1201 194 storres
        bw = ub - lb
1202 194 storres
        nbw = 0
1203 194 storres
        icAsInt = int(ic * toIntegerFactor)
1204 194 storres
        #### The following ratio is always >= 1. In case we may want to
1205 197 storres
        #    enlarge the interval
1206 194 storres
        curTaylErrRat = polyApproxAccur / terr
1207 197 storres
        ### Make the  integral transformations.
1208 197 storres
        #### Bounds and interval center.
1209 194 storres
        intIc = int(ic * toIntegerFactor)
1210 194 storres
        intLb = int(lb * toIntegerFactor) - intIc
1211 194 storres
        intUb = int(ub * toIntegerFactor) - intIc
1212 194 storres
        #
1213 197 storres
        #### Polynomials
1214 194 storres
        basisConstructionTime         = cputime()
1215 194 storres
        ##### To a polynomial with rational coefficients with rational arguments
1216 194 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
1217 194 storres
        ##### To a polynomial with rational coefficients with integer arguments
1218 194 storres
        ratIntP = \
1219 194 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
1220 197 storres
        #####  Ultimately a multivariate polynomial with integer coefficients
1221 197 storres
        #      with integer arguments.
1222 194 storres
        coppersmithTuple = \
1223 194 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
1224 194 storres
                                                        precision,
1225 194 storres
                                                        targetHardnessToRound,
1226 194 storres
                                                        i, t)
1227 194 storres
        #### Recover Coppersmith information.
1228 194 storres
        intIntP = coppersmithTuple[0]
1229 194 storres
        N = coppersmithTuple[1]
1230 194 storres
        nAtAlpha = N^alpha
1231 194 storres
        tBound = coppersmithTuple[2]
1232 194 storres
        leastCommonMultiple = coppersmithTuple[3]
1233 194 storres
        iBound = max(abs(intLb),abs(intUb))
1234 194 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
1235 194 storres
        basisConstructionsCount           += 1
1236 194 storres
        reductionTime                     = cputime()
1237 197 storres
        #### Compute the reduced polynomials.
1238 194 storres
        ccReducedPolynomialsList =  \
1239 212 storres
                slz_compute_coppersmith_reduced_polynomials(intIntP,
1240 212 storres
                                                            alpha,
1241 212 storres
                                                            N,
1242 212 storres
                                                            iBound,
1243 212 storres
                                                            tBound)
1244 194 storres
        if ccReducedPolynomialsList is None:
1245 194 storres
            raise Exception("Reduction failed.")
1246 194 storres
        reductionsFullTime    += cputime(reductionTime)
1247 194 storres
        reductionsCount       += 1
1248 194 storres
        if len(ccReducedPolynomialsList) < 2:
1249 194 storres
            print "Nothing to form resultants with."
1250 194 storres
            print
1251 194 storres
            coppCondFailedCount += 1
1252 194 storres
            coppCondFailed = True
1253 194 storres
            ##### Apply a different shrink factor according to
1254 194 storres
            #  the number of compliant polynomials.
1255 194 storres
            if len(ccReducedPolynomialsList) == 0:
1256 194 storres
                ub = lb + bw * noCoppersmithIntervalShrink
1257 194 storres
            else: # At least one compliant polynomial.
1258 194 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
1259 194 storres
            if ub > sdub:
1260 194 storres
                ub = sdub
1261 194 storres
            if lb == ub:
1262 194 storres
                raise Exception("Cant shrink interval \
1263 194 storres
                anymore to get Coppersmith condition.")
1264 194 storres
            nbw = 0
1265 194 storres
            continue
1266 194 storres
        #### We have at least two polynomials.
1267 194 storres
        #    Let us try to compute resultants.
1268 194 storres
        #    For each resultant computed, go for the solutions.
1269 194 storres
        ##### Build the pairs list.
1270 194 storres
        polyPairsList           = []
1271 194 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
1272 194 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
1273 194 storres
                                         len(ccReducedPolynomialsList)):
1274 194 storres
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
1275 194 storres
                                      ccReducedPolynomialsList[polyInnerIndex]))
1276 197 storres
        #### Actual root search.
1277 197 storres
        rootsSet            = set()
1278 197 storres
        hasNonNullResultant = False
1279 194 storres
        for polyPair in polyPairsList:
1280 197 storres
            if hasNonNullResultant:
1281 197 storres
                break
1282 197 storres
            resultantsComputationTime   = cputime()
1283 197 storres
            currentResultant = \
1284 197 storres
                slz_resultant(polyPair[0],
1285 197 storres
                              polyPair[1],
1286 197 storres
                              t)
1287 194 storres
            resultantsComputationsFullTime += cputime(resultantsComputationTime)
1288 194 storres
            resultantsComputationsCount    += 1
1289 197 storres
            if currentResultant is None:
1290 197 storres
                print "Nul resultant"
1291 197 storres
                continue # Next polyPair.
1292 197 storres
            else:
1293 194 storres
                hasNonNullResultant = True
1294 197 storres
            #### We have a non null resultant. From now on, whatever the
1295 197 storres
            #    root search yields, no extra root search is necessary.
1296 197 storres
            #### A constant resultant leads to no root. Root search is done.
1297 194 storres
            if currentResultant.degree() < 1:
1298 194 storres
                print "Resultant is constant:", currentResultant
1299 197 storres
                continue # Next polyPair and should break.
1300 197 storres
            #### Actual roots computation.
1301 197 storres
            rootsComputationTime       = cputime()
1302 194 storres
            ##### Compute i roots
1303 194 storres
            iRootsList = Zi(currentResultant).roots()
1304 197 storres
            ##### For each iRoot, compute the corresponding tRoots and
1305 197 storres
            #     and build populate the .rootsSet.
1306 194 storres
            for iRoot in iRootsList:
1307 194 storres
                ####### Roots returned by roots() are (value, multiplicity)
1308 194 storres
                #       tuples.
1309 194 storres
                #print "iRoot:", iRoot
1310 194 storres
                ###### Use the tRoot against each polynomial, alternatively.
1311 197 storres
                for indexInPair in range(0,2):
1312 197 storres
                    currentPolynomial = polyPair[indexInPair]
1313 194 storres
                    ####### If the polynomial is univariate, just drop it.
1314 194 storres
                    if len(currentPolynomial.variables()) < 2:
1315 194 storres
                        print "    Current polynomial is not in two variables."
1316 197 storres
                        continue # Next indexInPair
1317 194 storres
                    tRootsList = \
1318 194 storres
                        Zt(currentPolynomial.subs({currentPolynomial.variables()[0]:iRoot[0]})).roots()
1319 194 storres
                    ####### The tRootsList can be empty, hence the test.
1320 194 storres
                    if len(tRootsList) == 0:
1321 194 storres
                        print "    No t root."
1322 197 storres
                        continue # Next indexInPair
1323 194 storres
                    for tRoot in tRootsList:
1324 197 storres
                        rootsSet.add((iRoot[0], tRoot[0]))
1325 197 storres
            # End of roots computation.
1326 197 storres
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
1327 197 storres
            rootsComputationsCount      +=  1
1328 197 storres
        # End loop for polyPair in polyParsList.  Will break at next iteration.
1329 197 storres
        # since a non null resultant was found.
1330 197 storres
        #### Prepare for results for the current interval..
1331 194 storres
        intervalResultsList = []
1332 194 storres
        intervalResultsList.append((lb, ub))
1333 194 storres
        #### Check roots.
1334 194 storres
        rootsResultsList = []
1335 197 storres
        for root in rootsSet:
1336 194 storres
            specificRootResultsList = []
1337 194 storres
            failingBounds = []
1338 194 storres
            intIntPdivN = intIntP(root[0], root[1]) / N
1339 194 storres
            if int(intIntPdivN) != intIntPdivN:
1340 194 storres
                continue # Next root
1341 194 storres
            # Root qualifies for modular equation, test it for hardness to round.
1342 194 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + root[0]) / toIntegerFactor)
1343 194 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
1344 194 storres
            #print scalingFunction
1345 194 storres
            scaledHardToRoundCaseAsFloat = \
1346 194 storres
                scalingFunction(hardToRoundCaseAsFloat)
1347 194 storres
            print "Candidate HTRNc at x =", \
1348 194 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
1349 194 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
1350 194 storres
                           function,
1351 194 storres
                           2^-(targetHardnessToRound),
1352 194 storres
                           RRR):
1353 194 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
1354 194 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
1355 194 storres
                    print "Found in interval."
1356 194 storres
                else:
1357 194 storres
                    print "Found out of interval."
1358 194 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
1359 194 storres
                # Check the root is in the bounds
1360 194 storres
                if abs(root[0]) > iBound or abs(root[1]) > tBound:
1361 197 storres
                    print "Root", root, "is out of bounds for modular equation."
1362 194 storres
                    if abs(root[0]) > iBound:
1363 194 storres
                        print "root[0]:", root[0]
1364 194 storres
                        print "i bound:", iBound
1365 194 storres
                        failingBounds.append('i')
1366 194 storres
                        failingBounds.append(root[0])
1367 194 storres
                        failingBounds.append(iBound)
1368 194 storres
                    if abs(root[1]) > tBound:
1369 194 storres
                        print "root[1]:", root[1]
1370 194 storres
                        print "t bound:", tBound
1371 194 storres
                        failingBounds.append('t')
1372 194 storres
                        failingBounds.append(root[1])
1373 194 storres
                        failingBounds.append(tBound)
1374 194 storres
                if len(failingBounds) > 0:
1375 194 storres
                    specificRootResultsList.append(failingBounds)
1376 194 storres
            else: # From slz_is_htrn...
1377 194 storres
                print "is not an HTRN case."
1378 194 storres
            if len(specificRootResultsList) > 0:
1379 194 storres
                rootsResultsList.append(specificRootResultsList)
1380 194 storres
        if len(rootsResultsList) > 0:
1381 194 storres
            intervalResultsList.append(rootsResultsList)
1382 197 storres
        ### Check if a non null resultant was found. If not shrink the interval.
1383 197 storres
        if not hasNonNullResultant:
1384 197 storres
            print "Only null resultants for this reduction, shrinking interval."
1385 197 storres
            resultCondFailed      =  True
1386 197 storres
            resultCondFailedCount += 1
1387 197 storres
            ### Shrink interval for next iteration.
1388 197 storres
            ub = lb + bw * onlyNullResultantsShrink
1389 197 storres
            if ub > sdub:
1390 197 storres
                ub = sdub
1391 197 storres
            nbw = 0
1392 197 storres
            continue
1393 194 storres
        #### An intervalResultsList has at least the bounds.
1394 194 storres
        globalResultsList.append(intervalResultsList)
1395 194 storres
        #### Compute an incremented width for next upper bound, only
1396 194 storres
        #    if not Coppersmith condition nor resultant condition
1397 194 storres
        #    failed at the previous run.
1398 194 storres
        if not coppCondFailed and not resultCondFailed:
1399 194 storres
            nbw = noErrorIntervalStretch * bw
1400 194 storres
        else:
1401 194 storres
            nbw = bw
1402 194 storres
        ##### Reset the failure flags. They will be raised
1403 194 storres
        #     again if needed.
1404 194 storres
        coppCondFailed   = False
1405 194 storres
        resultCondFailed = False
1406 194 storres
        #### For next iteration (at end of loop)
1407 194 storres
        #print "nbw:", nbw
1408 194 storres
        lb  = ub
1409 194 storres
        ub += nbw
1410 194 storres
        if ub > sdub:
1411 194 storres
            ub = sdub
1412 194 storres
        print
1413 194 storres
    # End while True
1414 194 storres
    ## Main loop just ended.
1415 194 storres
    globalWallTime = walltime(wallTimeStart)
1416 194 storres
    globalCpuTime  = cputime(cpuTimeStart)
1417 194 storres
    ## Output results
1418 194 storres
    print ; print "Intervals and HTRNs" ; print
1419 194 storres
    for intervalResultsList in globalResultsList:
1420 222 storres
        intervalResultString = "[" + str(intervalResultsList[0][0]) +\
1421 222 storres
                               "," + str(intervalResultsList[0][1])  + "]"
1422 222 storres
        print intervalResultString,
1423 194 storres
        if len(intervalResultsList) > 1:
1424 194 storres
            rootsResultsList = intervalResultsList[1]
1425 222 storres
            specificRootResultIndex = 0
1426 194 storres
            for specificRootResultsList in rootsResultsList:
1427 222 storres
                if specificRootResultIndex == 0:
1428 222 storres
                    print "\t", specificRootResultsList[0],
1429 222 storres
                else:
1430 222 storres
                    print " " * len(intervalResultString), "\t", \
1431 222 storres
                          specificRootResultsList[0],
1432 194 storres
                if len(specificRootResultsList) > 1:
1433 222 storres
                    print specificRootResultsList[1]
1434 222 storres
                specificRootResultIndex += 1
1435 194 storres
        print ; print
1436 194 storres
    #print globalResultsList
1437 194 storres
    #
1438 194 storres
    print "Timers and counters"
1439 194 storres
    print
1440 194 storres
    print "Number of iterations:", iterCount
1441 194 storres
    print "Taylor condition failures:", taylCondFailedCount
1442 194 storres
    print "Coppersmith condition failures:", coppCondFailedCount
1443 194 storres
    print "Resultant condition failures:", resultCondFailedCount
1444 194 storres
    print "Iterations count: ", iterCount
1445 194 storres
    print "Number of intervals:", len(globalResultsList)
1446 194 storres
    print "Number of basis constructions:", basisConstructionsCount
1447 194 storres
    print "Total CPU time spent in basis constructions:", \
1448 194 storres
        basisConstructionsFullTime
1449 194 storres
    if basisConstructionsCount != 0:
1450 194 storres
        print "Average basis construction CPU time:", \
1451 194 storres
            basisConstructionsFullTime/basisConstructionsCount
1452 194 storres
    print "Number of reductions:", reductionsCount
1453 194 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
1454 194 storres
    if reductionsCount != 0:
1455 194 storres
        print "Average reduction CPU time:", \
1456 194 storres
            reductionsFullTime/reductionsCount
1457 194 storres
    print "Number of resultants computation rounds:", \
1458 194 storres
        resultantsComputationsCount
1459 194 storres
    print "Total CPU time spent in resultants computation rounds:", \
1460 194 storres
        resultantsComputationsFullTime
1461 194 storres
    if resultantsComputationsCount != 0:
1462 194 storres
        print "Average resultants computation round CPU time:", \
1463 194 storres
            resultantsComputationsFullTime/resultantsComputationsCount
1464 194 storres
    print "Number of root finding rounds:", rootsComputationsCount
1465 194 storres
    print "Total CPU time spent in roots finding rounds:", \
1466 194 storres
        rootsComputationsFullTime
1467 194 storres
    if rootsComputationsCount != 0:
1468 194 storres
        print "Average roots finding round CPU time:", \
1469 194 storres
            rootsComputationsFullTime/rootsComputationsCount
1470 194 storres
    print "Global Wall time:", globalWallTime
1471 194 storres
    print "Global CPU time:", globalCpuTime
1472 194 storres
    ## Output counters
1473 194 storres
# End srs_runSLZ-v02
1474 194 storres
1475 212 storres
def srs_run_SLZ_v03(inputFunction,
1476 212 storres
                    inputLowerBound,
1477 212 storres
                    inputUpperBound,
1478 212 storres
                    alpha,
1479 212 storres
                    degree,
1480 212 storres
                    precision,
1481 212 storres
                    emin,
1482 212 storres
                    emax,
1483 212 storres
                    targetHardnessToRound,
1484 212 storres
                    debug = False):
1485 212 storres
    """
1486 212 storres
    Changes from V2:
1487 212 storres
        Root search is changed:
1488 212 storres
            - we compute the resultants in i and in t;
1489 212 storres
            - we compute the roots set of each of these resultants;
1490 212 storres
            - we combine all the possible pairs between the two sets;
1491 212 storres
            - we check these pairs in polynomials for correctness.
1492 212 storres
    Changes from V1:
1493 212 storres
        1- check for roots as soon as a resultant is computed;
1494 212 storres
        2- once a non null resultant is found, check for roots;
1495 212 storres
        3- constant resultant == no root.
1496 212 storres
    """
1497 212 storres
1498 212 storres
    if debug:
1499 212 storres
        print "Function                :", inputFunction
1500 212 storres
        print "Lower bound             :", inputLowerBound
1501 212 storres
        print "Upper bounds            :", inputUpperBound
1502 212 storres
        print "Alpha                   :", alpha
1503 212 storres
        print "Degree                  :", degree
1504 212 storres
        print "Precision               :", precision
1505 212 storres
        print "Emin                    :", emin
1506 212 storres
        print "Emax                    :", emax
1507 212 storres
        print "Target hardness-to-round:", targetHardnessToRound
1508 212 storres
        print
1509 212 storres
    ## Important constants.
1510 212 storres
    ### Stretch the interval if no error happens.
1511 212 storres
    noErrorIntervalStretch = 1 + 2^(-5)
1512 212 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
1513 212 storres
    #   by the following factor.
1514 212 storres
    noCoppersmithIntervalShrink = 1/2
1515 212 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
1516 212 storres
    #   shrink the interval by the following factor.
1517 212 storres
    oneCoppersmithIntervalShrink = 3/4
1518 212 storres
    #### If only null resultants are found, shrink the interval by the
1519 212 storres
    #    following factor.
1520 212 storres
    onlyNullResultantsShrink     = 3/4
1521 212 storres
    ## Structures.
1522 212 storres
    RRR         = RealField(precision)
1523 212 storres
    RRIF        = RealIntervalField(precision)
1524 212 storres
    ## Converting input bound into the "right" field.
1525 212 storres
    lowerBound = RRR(inputLowerBound)
1526 212 storres
    upperBound = RRR(inputUpperBound)
1527 212 storres
    ## Before going any further, check domain and image binade conditions.
1528 212 storres
    print inputFunction(1).n()
1529 212 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
1530 212 storres
    if output is None:
1531 212 storres
        print "Invalid domain/image binades. Domain:",\
1532 212 storres
        lowerBound, upperBound, "Images:", \
1533 212 storres
        inputFunction(lowerBound), inputFunction(upperBound)
1534 212 storres
        raise Exception("Invalid domain/image binades.")
1535 212 storres
    lb = output[0] ; ub = output[1]
1536 212 storres
    if lb != lowerBound or ub != upperBound:
1537 212 storres
        print "lb:", lb, " - ub:", ub
1538 212 storres
        print "Invalid domain/image binades. Domain:",\
1539 212 storres
        lowerBound, upperBound, "Images:", \
1540 212 storres
        inputFunction(lowerBound), inputFunction(upperBound)
1541 212 storres
        raise Exception("Invalid domain/image binades.")
1542 212 storres
    #
1543 212 storres
    ## Progam initialization
1544 212 storres
    ### Approximation polynomial accuracy and hardness to round.
1545 212 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
1546 212 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
1547 212 storres
    ### Significand to integer conversion ratio.
1548 212 storres
    toIntegerFactor           = 2^(precision-1)
1549 212 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
1550 212 storres
    ### Variables and rings for polynomials and root searching.
1551 212 storres
    i=var('i')
1552 212 storres
    t=var('t')
1553 212 storres
    inputFunctionVariable = inputFunction.variables()[0]
1554 212 storres
    function = inputFunction.subs({inputFunctionVariable:i})
1555 212 storres
    #  Polynomial Rings over the integers, for root finding.
1556 212 storres
    Zi = ZZ[i]
1557 212 storres
    Zt = ZZ[t]
1558 212 storres
    Zit = ZZ[i,t]
1559 212 storres
    ## Number of iterations limit.
1560 212 storres
    maxIter = 100000
1561 231 storres
    ## Set the variable name in Sollya.
1562 231 storres
    pobyso_name_free_variable_sa_so(str(function.variables()[0]))
1563 212 storres
    #
1564 212 storres
    ## Compute the scaled function and the degree, in their Sollya version
1565 212 storres
    #  once for all.
1566 212 storres
    (scaledf, sdlb, sdub, silb, siub) = \
1567 212 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
1568 212 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
1569 212 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
1570 212 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
1571 212 storres
    #
1572 212 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
1573 212 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
1574 212 storres
    (unscalingFunction, scalingFunction) = \
1575 212 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
1576 212 storres
    #print scalingFunction, unscalingFunction
1577 212 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
1578 212 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
1579 212 storres
    if internalSollyaPrec < 192:
1580 212 storres
        internalSollyaPrec = 192
1581 212 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
1582 212 storres
    print "Sollya internal precision:", internalSollyaPrec
1583 212 storres
    ## Some variables.
1584 212 storres
    ### General variables
1585 212 storres
    lb                  = sdlb
1586 212 storres
    ub                  = sdub
1587 212 storres
    nbw                 = 0
1588 212 storres
    intervalUlp         = ub.ulp()
1589 212 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
1590 212 storres
    ic                  = 0
1591 212 storres
    icAsInt             = 0    # Set from ic.
1592 212 storres
    solutionsSet        = set()
1593 212 storres
    tsErrorWidth        = []
1594 212 storres
    csErrorVectors      = []
1595 212 storres
    csVectorsResultants = []
1596 212 storres
    floatP              = 0  # Taylor polynomial.
1597 212 storres
    floatPcv            = 0  # Ditto with variable change.
1598 212 storres
    intvl               = "" # Taylor interval
1599 212 storres
    terr                = 0  # Taylor error.
1600 212 storres
    iterCount = 0
1601 212 storres
    htrnSet = set()
1602 212 storres
    ### Timers and counters.
1603 212 storres
    wallTimeStart                   = 0
1604 212 storres
    cpuTimeStart                    = 0
1605 212 storres
    taylCondFailedCount             = 0
1606 212 storres
    coppCondFailedCount             = 0
1607 212 storres
    resultCondFailedCount           = 0
1608 212 storres
    coppCondFailed                  = False
1609 212 storres
    resultCondFailed                = False
1610 212 storres
    globalResultsList               = []
1611 212 storres
    basisConstructionsCount         = 0
1612 212 storres
    basisConstructionsFullTime      = 0
1613 212 storres
    basisConstructionTime           = 0
1614 212 storres
    reductionsCount                 = 0
1615 212 storres
    reductionsFullTime              = 0
1616 212 storres
    reductionTime                   = 0
1617 212 storres
    resultantsComputationsCount     = 0
1618 212 storres
    resultantsComputationsFullTime  = 0
1619 212 storres
    resultantsComputationTime       = 0
1620 212 storres
    rootsComputationsCount          = 0
1621 212 storres
    rootsComputationsFullTime       = 0
1622 212 storres
    rootsComputationTime            = 0
1623 212 storres
    print
1624 212 storres
    ## Global times are started here.
1625 212 storres
    wallTimeStart                   = walltime()
1626 212 storres
    cpuTimeStart                    = cputime()
1627 212 storres
    ## Main loop.
1628 212 storres
    while True:
1629 212 storres
        if lb >= sdub:
1630 212 storres
            print "Lower bound reached upper bound."
1631 212 storres
            break
1632 212 storres
        if iterCount == maxIter:
1633 212 storres
            print "Reached maxIter. Aborting"
1634 212 storres
            break
1635 212 storres
        iterCount += 1
1636 212 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
1637 212 storres
            "log2(numbers)."
1638 212 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
1639 212 storres
        prceSo = slz_compute_polynomial_and_interval(scaledfSo,
1640 212 storres
                                                     degreeSo,
1641 212 storres
                                                     lb,
1642 212 storres
                                                     ub,
1643 212 storres
                                                     polyApproxAccur)
1644 212 storres
        ### Convert back the data into Sage space.
1645 212 storres
        (floatP, floatPcv, intvl, ic, terr) = \
1646 212 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
1647 212 storres
                                                 prceSo[1], prceSo[2],
1648 212 storres
                                                 prceSo[3]))
1649 212 storres
        intvl = RRIF(intvl)
1650 212 storres
        ## Clean-up Sollya stuff.
1651 212 storres
        for elem in prceSo:
1652 212 storres
            sollya_lib_clear_obj(elem)
1653 212 storres
        #print  floatP, floatPcv, intvl, ic, terr
1654 212 storres
        #print floatP
1655 212 storres
        #print intvl.endpoints()[0].n(), \
1656 212 storres
        #      ic.n(),
1657 212 storres
        #intvl.endpoints()[1].n()
1658 212 storres
        ### Check returned data.
1659 212 storres
        #### Is approximation error OK?
1660 212 storres
        if terr > polyApproxAccur:
1661 212 storres
            exceptionErrorMess  = \
1662 212 storres
                "Approximation failed - computed error:" + \
1663 212 storres
                str(terr) + " - target error: "
1664 212 storres
            exceptionErrorMess += \
1665 212 storres
                str(polyApproxAccur) + ". Aborting!"
1666 212 storres
            raise Exception(exceptionErrorMess)
1667 212 storres
        #### Is lower bound OK?
1668 212 storres
        if lb != intvl.endpoints()[0]:
1669 212 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
1670 212 storres
                               str(lb) + ". Aborting!"
1671 212 storres
            raise Exception(exceptionErrorMess)
1672 212 storres
        #### Set upper bound.
1673 212 storres
        if ub > intvl.endpoints()[1]:
1674 212 storres
            ub = intvl.endpoints()[1]
1675 212 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
1676 212 storres
            "log2(numbers)."
1677 212 storres
            taylCondFailedCount += 1
1678 212 storres
        #### Is interval not degenerate?
1679 212 storres
        if lb >= ub:
1680 212 storres
            exceptionErrorMess = "Degenerate interval: " + \
1681 212 storres
                                "lowerBound(" + str(lb) +\
1682 212 storres
                                ")>= upperBound(" + str(ub) + \
1683 212 storres
                                "). Aborting!"
1684 212 storres
            raise Exception(exceptionErrorMess)
1685 212 storres
        #### Is interval center ok?
1686 212 storres
        if ic <= lb or ic >= ub:
1687 212 storres
            exceptionErrorMess =  "Invalid interval center for " + \
1688 212 storres
                                str(lb) + ',' + str(ic) + ',' +  \
1689 212 storres
                                str(ub) + ". Aborting!"
1690 212 storres
            raise Exception(exceptionErrorMess)
1691 212 storres
        ##### Current interval width and reset future interval width.
1692 212 storres
        bw = ub - lb
1693 212 storres
        nbw = 0
1694 212 storres
        icAsInt = int(ic * toIntegerFactor)
1695 212 storres
        #### The following ratio is always >= 1. In case we may want to
1696 212 storres
        #    enlarge the interval
1697 212 storres
        curTaylErrRat = polyApproxAccur / terr
1698 212 storres
        ### Make the  integral transformations.
1699 212 storres
        #### Bounds and interval center.
1700 212 storres
        intIc = int(ic * toIntegerFactor)
1701 212 storres
        intLb = int(lb * toIntegerFactor) - intIc
1702 212 storres
        intUb = int(ub * toIntegerFactor) - intIc
1703 212 storres
        #
1704 212 storres
        #### Polynomials
1705 212 storres
        basisConstructionTime         = cputime()
1706 212 storres
        ##### To a polynomial with rational coefficients with rational arguments
1707 212 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
1708 212 storres
        ##### To a polynomial with rational coefficients with integer arguments
1709 212 storres
        ratIntP = \
1710 212 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
1711 212 storres
        #####  Ultimately a multivariate polynomial with integer coefficients
1712 212 storres
        #      with integer arguments.
1713 212 storres
        coppersmithTuple = \
1714 212 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
1715 212 storres
                                                        precision,
1716 212 storres
                                                        targetHardnessToRound,
1717 212 storres
                                                        i, t)
1718 212 storres
        #### Recover Coppersmith information.
1719 212 storres
        intIntP = coppersmithTuple[0]
1720 212 storres
        N = coppersmithTuple[1]
1721 212 storres
        nAtAlpha = N^alpha
1722 212 storres
        tBound = coppersmithTuple[2]
1723 212 storres
        leastCommonMultiple = coppersmithTuple[3]
1724 212 storres
        iBound = max(abs(intLb),abs(intUb))
1725 212 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
1726 212 storres
        basisConstructionsCount           += 1
1727 212 storres
        reductionTime                     = cputime()
1728 212 storres
        #### Compute the reduced polynomials.
1729 212 storres
        ccReducedPolynomialsList =  \
1730 212 storres
                slz_compute_coppersmith_reduced_polynomials(intIntP,
1731 212 storres
                                                            alpha,
1732 212 storres
                                                            N,
1733 212 storres
                                                            iBound,
1734 212 storres
                                                            tBound)
1735 212 storres
        if ccReducedPolynomialsList is None:
1736 212 storres
            raise Exception("Reduction failed.")
1737 212 storres
        reductionsFullTime    += cputime(reductionTime)
1738 212 storres
        reductionsCount       += 1
1739 212 storres
        if len(ccReducedPolynomialsList) < 2:
1740 212 storres
            print "Nothing to form resultants with."
1741 212 storres
            print
1742 212 storres
            coppCondFailedCount += 1
1743 212 storres
            coppCondFailed = True
1744 212 storres
            ##### Apply a different shrink factor according to
1745 212 storres
            #  the number of compliant polynomials.
1746 212 storres
            if len(ccReducedPolynomialsList) == 0:
1747 212 storres
                ub = lb + bw * noCoppersmithIntervalShrink
1748 212 storres
            else: # At least one compliant polynomial.
1749 212 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
1750 212 storres
            if ub > sdub:
1751 212 storres
                ub = sdub
1752 212 storres
            if lb == ub:
1753 212 storres
                raise Exception("Cant shrink interval \
1754 212 storres
                anymore to get Coppersmith condition.")
1755 212 storres
            nbw = 0
1756 212 storres
            continue
1757 212 storres
        #### We have at least two polynomials.
1758 212 storres
        #    Let us try to compute resultants.
1759 212 storres
        #    For each resultant computed, go for the solutions.
1760 212 storres
        ##### Build the pairs list.
1761 212 storres
        polyPairsList           = []
1762 212 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
1763 212 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
1764 212 storres
                                         len(ccReducedPolynomialsList)):
1765 212 storres
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
1766 212 storres
                                      ccReducedPolynomialsList[polyInnerIndex]))
1767 212 storres
        #### Actual root search.
1768 212 storres
        rootsSet            = set()
1769 212 storres
        hasNonNullResultant = False
1770 212 storres
        for polyPair in polyPairsList:
1771 212 storres
            if hasNonNullResultant:
1772 212 storres
                break
1773 212 storres
            resultantsComputationTime   = cputime()
1774 212 storres
            currentResultantI = \
1775 212 storres
                slz_resultant(polyPair[0],
1776 212 storres
                              polyPair[1],
1777 212 storres
                              t)
1778 212 storres
            resultantsComputationsCount    += 1
1779 212 storres
            if currentResultantI is None:
1780 212 storres
                resultantsComputationsFullTime +=  \
1781 212 storres
                    cputime(resultantsComputationTime)
1782 212 storres
                print "Nul resultant"
1783 212 storres
                continue # Next polyPair.
1784 212 storres
            currentResultantT = \
1785 212 storres
                slz_resultant(polyPair[0],
1786 212 storres
                              polyPair[1],
1787 212 storres
                              i)
1788 212 storres
            resultantsComputationsFullTime += cputime(resultantsComputationTime)
1789 212 storres
            resultantsComputationsCount    += 1
1790 212 storres
            if currentResultantT is None:
1791 212 storres
                print "Nul resultant"
1792 212 storres
                continue # Next polyPair.
1793 212 storres
            else:
1794 212 storres
                hasNonNullResultant = True
1795 212 storres
            #### We have a non null resultants pair. From now on, whatever the
1796 212 storres
            #    root search yields, no extra root search is necessary.
1797 212 storres
            #### A constant resultant leads to no root. Root search is done.
1798 212 storres
            if currentResultantI.degree() < 1:
1799 212 storres
                print "Resultant is constant:", currentResultantI
1800 212 storres
                break # Next polyPair and should break.
1801 212 storres
            if currentResultantT.degree() < 1:
1802 212 storres
                print "Resultant is constant:", currentResultantT
1803 212 storres
                break # Next polyPair and should break.
1804 212 storres
            #### Actual roots computation.
1805 212 storres
            rootsComputationTime       = cputime()
1806 212 storres
            ##### Compute i roots
1807 212 storres
            iRootsList = Zi(currentResultantI).roots()
1808 212 storres
            rootsComputationsCount      +=  1
1809 212 storres
            if len(iRootsList) == 0:
1810 212 storres
                rootsComputationsFullTime   =   cputime(rootsComputationTime)
1811 212 storres
                print "No roots in \"i\"."
1812 212 storres
                break # No roots in i.
1813 212 storres
            tRootsList = Zt(currentResultantT).roots()
1814 212 storres
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
1815 212 storres
            rootsComputationsCount      +=  1
1816 212 storres
            if len(tRootsList) == 0:
1817 212 storres
                print "No roots in \"t\"."
1818 212 storres
                break # No roots in i.
1819 212 storres
            ##### For each iRoot, get a tRoot and check against the polynomials.
1820 212 storres
            for iRoot in iRootsList:
1821 212 storres
                ####### Roots returned by roots() are (value, multiplicity)
1822 212 storres
                #       tuples.
1823 212 storres
                #print "iRoot:", iRoot
1824 212 storres
                for tRoot in tRootsList:
1825 212 storres
                ###### Use the tRoot against each polynomial, alternatively.
1826 212 storres
                    if polyPair[0](iRoot[0],tRoot[0]) != 0:
1827 212 storres
                        continue
1828 212 storres
                    if polyPair[1](iRoot[0],tRoot[0]) != 0:
1829 212 storres
                        continue
1830 212 storres
                    rootsSet.add((iRoot[0], tRoot[0]))
1831 212 storres
            # End of roots computation.
1832 212 storres
        # End loop for polyPair in polyParsList.  Will break at next iteration.
1833 212 storres
        # since a non null resultant was found.
1834 212 storres
        #### Prepare for results for the current interval..
1835 212 storres
        intervalResultsList = []
1836 212 storres
        intervalResultsList.append((lb, ub))
1837 212 storres
        #### Check roots.
1838 212 storres
        rootsResultsList = []
1839 212 storres
        for root in rootsSet:
1840 212 storres
            specificRootResultsList = []
1841 212 storres
            failingBounds = []
1842 212 storres
            intIntPdivN = intIntP(root[0], root[1]) / N
1843 212 storres
            if int(intIntPdivN) != intIntPdivN:
1844 212 storres
                continue # Next root
1845 212 storres
            # Root qualifies for modular equation, test it for hardness to round.
1846 212 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + root[0]) / toIntegerFactor)
1847 212 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
1848 212 storres
            #print scalingFunction
1849 212 storres
            scaledHardToRoundCaseAsFloat = \
1850 212 storres
                scalingFunction(hardToRoundCaseAsFloat)
1851 212 storres
            print "Candidate HTRNc at x =", \
1852 212 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
1853 212 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
1854 212 storres
                           function,
1855 212 storres
                           2^-(targetHardnessToRound),
1856 212 storres
                           RRR):
1857 212 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
1858 212 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
1859 212 storres
                    print "Found in interval."
1860 212 storres
                else:
1861 212 storres
                    print "Found out of interval."
1862 212 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
1863 212 storres
                # Check the root is in the bounds
1864 212 storres
                if abs(root[0]) > iBound or abs(root[1]) > tBound:
1865 212 storres
                    print "Root", root, "is out of bounds for modular equation."
1866 212 storres
                    if abs(root[0]) > iBound:
1867 212 storres
                        print "root[0]:", root[0]
1868 212 storres
                        print "i bound:", iBound
1869 212 storres
                        failingBounds.append('i')
1870 212 storres
                        failingBounds.append(root[0])
1871 212 storres
                        failingBounds.append(iBound)
1872 212 storres
                    if abs(root[1]) > tBound:
1873 212 storres
                        print "root[1]:", root[1]
1874 212 storres
                        print "t bound:", tBound
1875 212 storres
                        failingBounds.append('t')
1876 212 storres
                        failingBounds.append(root[1])
1877 212 storres
                        failingBounds.append(tBound)
1878 212 storres
                if len(failingBounds) > 0:
1879 212 storres
                    specificRootResultsList.append(failingBounds)
1880 212 storres
            else: # From slz_is_htrn...
1881 212 storres
                print "is not an HTRN case."
1882 212 storres
            if len(specificRootResultsList) > 0:
1883 212 storres
                rootsResultsList.append(specificRootResultsList)
1884 212 storres
        if len(rootsResultsList) > 0:
1885 212 storres
            intervalResultsList.append(rootsResultsList)
1886 212 storres
        ### Check if a non null resultant was found. If not shrink the interval.
1887 212 storres
        if not hasNonNullResultant:
1888 212 storres
            print "Only null resultants for this reduction, shrinking interval."
1889 212 storres
            resultCondFailed      =  True
1890 212 storres
            resultCondFailedCount += 1
1891 212 storres
            ### Shrink interval for next iteration.
1892 212 storres
            ub = lb + bw * onlyNullResultantsShrink
1893 212 storres
            if ub > sdub:
1894 212 storres
                ub = sdub
1895 212 storres
            nbw = 0
1896 212 storres
            continue
1897 212 storres
        #### An intervalResultsList has at least the bounds.
1898 212 storres
        globalResultsList.append(intervalResultsList)
1899 212 storres
        #### Compute an incremented width for next upper bound, only
1900 212 storres
        #    if not Coppersmith condition nor resultant condition
1901 212 storres
        #    failed at the previous run.
1902 212 storres
        if not coppCondFailed and not resultCondFailed:
1903 212 storres
            nbw = noErrorIntervalStretch * bw
1904 212 storres
        else:
1905 212 storres
            nbw = bw
1906 212 storres
        ##### Reset the failure flags. They will be raised
1907 212 storres
        #     again if needed.
1908 212 storres
        coppCondFailed   = False
1909 212 storres
        resultCondFailed = False
1910 212 storres
        #### For next iteration (at end of loop)
1911 212 storres
        #print "nbw:", nbw
1912 212 storres
        lb  = ub
1913 212 storres
        ub += nbw
1914 212 storres
        if ub > sdub:
1915 212 storres
            ub = sdub
1916 212 storres
        print
1917 212 storres
    # End while True
1918 212 storres
    ## Main loop just ended.
1919 212 storres
    globalWallTime = walltime(wallTimeStart)
1920 212 storres
    globalCpuTime  = cputime(cpuTimeStart)
1921 212 storres
    ## Output results
1922 212 storres
    print ; print "Intervals and HTRNs" ; print
1923 212 storres
    for intervalResultsList in globalResultsList:
1924 222 storres
        intervalResultString = "[" + str(intervalResultsList[0][0]) +\
1925 222 storres
                               "," + str(intervalResultsList[0][1])  + "]"
1926 222 storres
        print intervalResultString,
1927 212 storres
        if len(intervalResultsList) > 1:
1928 212 storres
            rootsResultsList = intervalResultsList[1]
1929 222 storres
            specificRootResultIndex = 0
1930 212 storres
            for specificRootResultsList in rootsResultsList:
1931 222 storres
                if specificRootResultIndex == 0:
1932 222 storres
                    print "\t", specificRootResultsList[0],
1933 222 storres
                else:
1934 222 storres
                    print " " * len(intervalResultString), "\t", \
1935 222 storres
                          specificRootResultsList[0],
1936 212 storres
                if len(specificRootResultsList) > 1:
1937 222 storres
                    print specificRootResultsList[1]
1938 222 storres
                specificRootResultIndex += 1
1939 212 storres
        print ; print
1940 212 storres
    #print globalResultsList
1941 212 storres
    #
1942 212 storres
    print "Timers and counters"
1943 212 storres
    print
1944 212 storres
    print "Number of iterations:", iterCount
1945 212 storres
    print "Taylor condition failures:", taylCondFailedCount
1946 212 storres
    print "Coppersmith condition failures:", coppCondFailedCount
1947 212 storres
    print "Resultant condition failures:", resultCondFailedCount
1948 212 storres
    print "Iterations count: ", iterCount
1949 212 storres
    print "Number of intervals:", len(globalResultsList)
1950 212 storres
    print "Number of basis constructions:", basisConstructionsCount
1951 212 storres
    print "Total CPU time spent in basis constructions:", \
1952 212 storres
        basisConstructionsFullTime
1953 212 storres
    if basisConstructionsCount != 0:
1954 212 storres
        print "Average basis construction CPU time:", \
1955 212 storres
            basisConstructionsFullTime/basisConstructionsCount
1956 212 storres
    print "Number of reductions:", reductionsCount
1957 212 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
1958 212 storres
    if reductionsCount != 0:
1959 212 storres
        print "Average reduction CPU time:", \
1960 212 storres
            reductionsFullTime/reductionsCount
1961 212 storres
    print "Number of resultants computation rounds:", \
1962 212 storres
        resultantsComputationsCount
1963 212 storres
    print "Total CPU time spent in resultants computation rounds:", \
1964 212 storres
        resultantsComputationsFullTime
1965 212 storres
    if resultantsComputationsCount != 0:
1966 212 storres
        print "Average resultants computation round CPU time:", \
1967 212 storres
            resultantsComputationsFullTime/resultantsComputationsCount
1968 212 storres
    print "Number of root finding rounds:", rootsComputationsCount
1969 212 storres
    print "Total CPU time spent in roots finding rounds:", \
1970 212 storres
        rootsComputationsFullTime
1971 212 storres
    if rootsComputationsCount != 0:
1972 212 storres
        print "Average roots finding round CPU time:", \
1973 212 storres
            rootsComputationsFullTime/rootsComputationsCount
1974 212 storres
    print "Global Wall time:", globalWallTime
1975 212 storres
    print "Global CPU time:", globalCpuTime
1976 212 storres
    ## Output counters
1977 212 storres
# End srs_runSLZ-v03
1978 212 storres
1979 213 storres
def srs_run_SLZ_v04(inputFunction,
1980 212 storres
                    inputLowerBound,
1981 212 storres
                    inputUpperBound,
1982 212 storres
                    alpha,
1983 212 storres
                    degree,
1984 212 storres
                    precision,
1985 212 storres
                    emin,
1986 212 storres
                    emax,
1987 212 storres
                    targetHardnessToRound,
1988 212 storres
                    debug = False):
1989 212 storres
    """
1990 213 storres
    Changes from V3:
1991 213 storres
        Root search is changed again:
1992 213 storres
            - only resultants in i are computed;
1993 219 storres
            - roots in i are searched for;
1994 213 storres
            - if any, they are tested for hardness-to-round.
1995 212 storres
    Changes from V2:
1996 212 storres
        Root search is changed:
1997 212 storres
            - we compute the resultants in i and in t;
1998 212 storres
            - we compute the roots set of each of these resultants;
1999 212 storres
            - we combine all the possible pairs between the two sets;
2000 212 storres
            - we check these pairs in polynomials for correctness.
2001 212 storres
    Changes from V1:
2002 212 storres
        1- check for roots as soon as a resultant is computed;
2003 212 storres
        2- once a non null resultant is found, check for roots;
2004 212 storres
        3- constant resultant == no root.
2005 212 storres
    """
2006 212 storres
2007 212 storres
    if debug:
2008 212 storres
        print "Function                :", inputFunction
2009 212 storres
        print "Lower bound             :", inputLowerBound
2010 212 storres
        print "Upper bounds            :", inputUpperBound
2011 212 storres
        print "Alpha                   :", alpha
2012 212 storres
        print "Degree                  :", degree
2013 212 storres
        print "Precision               :", precision
2014 212 storres
        print "Emin                    :", emin
2015 212 storres
        print "Emax                    :", emax
2016 212 storres
        print "Target hardness-to-round:", targetHardnessToRound
2017 212 storres
        print
2018 212 storres
    ## Important constants.
2019 212 storres
    ### Stretch the interval if no error happens.
2020 212 storres
    noErrorIntervalStretch = 1 + 2^(-5)
2021 212 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
2022 212 storres
    #   by the following factor.
2023 212 storres
    noCoppersmithIntervalShrink = 1/2
2024 212 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
2025 212 storres
    #   shrink the interval by the following factor.
2026 212 storres
    oneCoppersmithIntervalShrink = 3/4
2027 212 storres
    #### If only null resultants are found, shrink the interval by the
2028 212 storres
    #    following factor.
2029 212 storres
    onlyNullResultantsShrink     = 3/4
2030 212 storres
    ## Structures.
2031 212 storres
    RRR         = RealField(precision)
2032 212 storres
    RRIF        = RealIntervalField(precision)
2033 212 storres
    ## Converting input bound into the "right" field.
2034 212 storres
    lowerBound = RRR(inputLowerBound)
2035 212 storres
    upperBound = RRR(inputUpperBound)
2036 212 storres
    ## Before going any further, check domain and image binade conditions.
2037 212 storres
    print inputFunction(1).n()
2038 212 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
2039 212 storres
    if output is None:
2040 212 storres
        print "Invalid domain/image binades. Domain:",\
2041 212 storres
        lowerBound, upperBound, "Images:", \
2042 212 storres
        inputFunction(lowerBound), inputFunction(upperBound)
2043 212 storres
        raise Exception("Invalid domain/image binades.")
2044 212 storres
    lb = output[0] ; ub = output[1]
2045 212 storres
    if lb != lowerBound or ub != upperBound:
2046 212 storres
        print "lb:", lb, " - ub:", ub
2047 212 storres
        print "Invalid domain/image binades. Domain:",\
2048 212 storres
        lowerBound, upperBound, "Images:", \
2049 212 storres
        inputFunction(lowerBound), inputFunction(upperBound)
2050 212 storres
        raise Exception("Invalid domain/image binades.")
2051 212 storres
    #
2052 212 storres
    ## Progam initialization
2053 212 storres
    ### Approximation polynomial accuracy and hardness to round.
2054 212 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
2055 212 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
2056 212 storres
    ### Significand to integer conversion ratio.
2057 212 storres
    toIntegerFactor           = 2^(precision-1)
2058 212 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
2059 212 storres
    ### Variables and rings for polynomials and root searching.
2060 212 storres
    i=var('i')
2061 212 storres
    t=var('t')
2062 212 storres
    inputFunctionVariable = inputFunction.variables()[0]
2063 212 storres
    function = inputFunction.subs({inputFunctionVariable:i})
2064 212 storres
    #  Polynomial Rings over the integers, for root finding.
2065 212 storres
    Zi = ZZ[i]
2066 212 storres
    Zt = ZZ[t]
2067 212 storres
    Zit = ZZ[i,t]
2068 212 storres
    ## Number of iterations limit.
2069 212 storres
    maxIter = 100000
2070 212 storres
    #
2071 231 storres
    ## Set the variable name in Sollya.
2072 231 storres
    pobyso_name_free_variable_sa_so(str(function.variables()[0]))
2073 212 storres
    ## Compute the scaled function and the degree, in their Sollya version
2074 212 storres
    #  once for all.
2075 212 storres
    (scaledf, sdlb, sdub, silb, siub) = \
2076 212 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
2077 212 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
2078 212 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
2079 212 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
2080 212 storres
    #
2081 212 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
2082 212 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
2083 212 storres
    (unscalingFunction, scalingFunction) = \
2084 212 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
2085 212 storres
    #print scalingFunction, unscalingFunction
2086 212 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
2087 212 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
2088 212 storres
    if internalSollyaPrec < 192:
2089 212 storres
        internalSollyaPrec = 192
2090 212 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
2091 212 storres
    print "Sollya internal precision:", internalSollyaPrec
2092 212 storres
    ## Some variables.
2093 212 storres
    ### General variables
2094 212 storres
    lb                  = sdlb
2095 212 storres
    ub                  = sdub
2096 212 storres
    nbw                 = 0
2097 212 storres
    intervalUlp         = ub.ulp()
2098 212 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
2099 212 storres
    ic                  = 0
2100 212 storres
    icAsInt             = 0    # Set from ic.
2101 212 storres
    solutionsSet        = set()
2102 212 storres
    tsErrorWidth        = []
2103 212 storres
    csErrorVectors      = []
2104 212 storres
    csVectorsResultants = []
2105 212 storres
    floatP              = 0  # Taylor polynomial.
2106 212 storres
    floatPcv            = 0  # Ditto with variable change.
2107 212 storres
    intvl               = "" # Taylor interval
2108 212 storres
    terr                = 0  # Taylor error.
2109 212 storres
    iterCount = 0
2110 212 storres
    htrnSet = set()
2111 212 storres
    ### Timers and counters.
2112 212 storres
    wallTimeStart                   = 0
2113 212 storres
    cpuTimeStart                    = 0
2114 212 storres
    taylCondFailedCount             = 0
2115 212 storres
    coppCondFailedCount             = 0
2116 212 storres
    resultCondFailedCount           = 0
2117 212 storres
    coppCondFailed                  = False
2118 212 storres
    resultCondFailed                = False
2119 212 storres
    globalResultsList               = []
2120 212 storres
    basisConstructionsCount         = 0
2121 212 storres
    basisConstructionsFullTime      = 0
2122 212 storres
    basisConstructionTime           = 0
2123 212 storres
    reductionsCount                 = 0
2124 212 storres
    reductionsFullTime              = 0
2125 212 storres
    reductionTime                   = 0
2126 212 storres
    resultantsComputationsCount     = 0
2127 212 storres
    resultantsComputationsFullTime  = 0
2128 212 storres
    resultantsComputationTime       = 0
2129 212 storres
    rootsComputationsCount          = 0
2130 212 storres
    rootsComputationsFullTime       = 0
2131 212 storres
    rootsComputationTime            = 0
2132 212 storres
    print
2133 212 storres
    ## Global times are started here.
2134 212 storres
    wallTimeStart                   = walltime()
2135 212 storres
    cpuTimeStart                    = cputime()
2136 212 storres
    ## Main loop.
2137 212 storres
    while True:
2138 212 storres
        if lb >= sdub:
2139 212 storres
            print "Lower bound reached upper bound."
2140 212 storres
            break
2141 212 storres
        if iterCount == maxIter:
2142 212 storres
            print "Reached maxIter. Aborting"
2143 212 storres
            break
2144 212 storres
        iterCount += 1
2145 212 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
2146 212 storres
            "log2(numbers)."
2147 212 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
2148 212 storres
        prceSo = slz_compute_polynomial_and_interval(scaledfSo,
2149 212 storres
                                                     degreeSo,
2150 212 storres
                                                     lb,
2151 212 storres
                                                     ub,
2152 212 storres
                                                     polyApproxAccur)
2153 212 storres
        ### Convert back the data into Sage space.
2154 212 storres
        (floatP, floatPcv, intvl, ic, terr) = \
2155 212 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
2156 212 storres
                                                 prceSo[1], prceSo[2],
2157 212 storres
                                                 prceSo[3]))
2158 212 storres
        intvl = RRIF(intvl)
2159 212 storres
        ## Clean-up Sollya stuff.
2160 212 storres
        for elem in prceSo:
2161 212 storres
            sollya_lib_clear_obj(elem)
2162 212 storres
        #print  floatP, floatPcv, intvl, ic, terr
2163 212 storres
        #print floatP
2164 212 storres
        #print intvl.endpoints()[0].n(), \
2165 212 storres
        #      ic.n(),
2166 212 storres
        #intvl.endpoints()[1].n()
2167 212 storres
        ### Check returned data.
2168 212 storres
        #### Is approximation error OK?
2169 212 storres
        if terr > polyApproxAccur:
2170 212 storres
            exceptionErrorMess  = \
2171 212 storres
                "Approximation failed - computed error:" + \
2172 212 storres
                str(terr) + " - target error: "
2173 212 storres
            exceptionErrorMess += \
2174 212 storres
                str(polyApproxAccur) + ". Aborting!"
2175 212 storres
            raise Exception(exceptionErrorMess)
2176 212 storres
        #### Is lower bound OK?
2177 212 storres
        if lb != intvl.endpoints()[0]:
2178 212 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
2179 212 storres
                               str(lb) + ". Aborting!"
2180 212 storres
            raise Exception(exceptionErrorMess)
2181 212 storres
        #### Set upper bound.
2182 212 storres
        if ub > intvl.endpoints()[1]:
2183 212 storres
            ub = intvl.endpoints()[1]
2184 212 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
2185 212 storres
            "log2(numbers)."
2186 212 storres
            taylCondFailedCount += 1
2187 212 storres
        #### Is interval not degenerate?
2188 212 storres
        if lb >= ub:
2189 212 storres
            exceptionErrorMess = "Degenerate interval: " + \
2190 212 storres
                                "lowerBound(" + str(lb) +\
2191 212 storres
                                ")>= upperBound(" + str(ub) + \
2192 212 storres
                                "). Aborting!"
2193 212 storres
            raise Exception(exceptionErrorMess)
2194 212 storres
        #### Is interval center ok?
2195 212 storres
        if ic <= lb or ic >= ub:
2196 212 storres
            exceptionErrorMess =  "Invalid interval center for " + \
2197 212 storres
                                str(lb) + ',' + str(ic) + ',' +  \
2198 212 storres
                                str(ub) + ". Aborting!"
2199 212 storres
            raise Exception(exceptionErrorMess)
2200 212 storres
        ##### Current interval width and reset future interval width.
2201 212 storres
        bw = ub - lb
2202 212 storres
        nbw = 0
2203 212 storres
        icAsInt = int(ic * toIntegerFactor)
2204 212 storres
        #### The following ratio is always >= 1. In case we may want to
2205 212 storres
        #    enlarge the interval
2206 212 storres
        curTaylErrRat = polyApproxAccur / terr
2207 212 storres
        ### Make the  integral transformations.
2208 212 storres
        #### Bounds and interval center.
2209 212 storres
        intIc = int(ic * toIntegerFactor)
2210 212 storres
        intLb = int(lb * toIntegerFactor) - intIc
2211 212 storres
        intUb = int(ub * toIntegerFactor) - intIc
2212 212 storres
        #
2213 212 storres
        #### Polynomials
2214 212 storres
        basisConstructionTime         = cputime()
2215 212 storres
        ##### To a polynomial with rational coefficients with rational arguments
2216 212 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
2217 212 storres
        ##### To a polynomial with rational coefficients with integer arguments
2218 212 storres
        ratIntP = \
2219 212 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
2220 212 storres
        #####  Ultimately a multivariate polynomial with integer coefficients
2221 212 storres
        #      with integer arguments.
2222 212 storres
        coppersmithTuple = \
2223 212 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
2224 212 storres
                                                        precision,
2225 212 storres
                                                        targetHardnessToRound,
2226 212 storres
                                                        i, t)
2227 212 storres
        #### Recover Coppersmith information.
2228 212 storres
        intIntP = coppersmithTuple[0]
2229 212 storres
        N = coppersmithTuple[1]
2230 212 storres
        nAtAlpha = N^alpha
2231 212 storres
        tBound = coppersmithTuple[2]
2232 212 storres
        leastCommonMultiple = coppersmithTuple[3]
2233 212 storres
        iBound = max(abs(intLb),abs(intUb))
2234 212 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
2235 212 storres
        basisConstructionsCount           += 1
2236 212 storres
        reductionTime                     = cputime()
2237 212 storres
        #### Compute the reduced polynomials.
2238 212 storres
        ccReducedPolynomialsList =  \
2239 213 storres
                slz_compute_coppersmith_reduced_polynomials(intIntP,
2240 213 storres
                                                            alpha,
2241 213 storres
                                                            N,
2242 213 storres
                                                            iBound,
2243 213 storres
                                                            tBound)
2244 212 storres
        if ccReducedPolynomialsList is None:
2245 212 storres
            raise Exception("Reduction failed.")
2246 212 storres
        reductionsFullTime    += cputime(reductionTime)
2247 212 storres
        reductionsCount       += 1
2248 212 storres
        if len(ccReducedPolynomialsList) < 2:
2249 212 storres
            print "Nothing to form resultants with."
2250 212 storres
            print
2251 212 storres
            coppCondFailedCount += 1
2252 212 storres
            coppCondFailed = True
2253 212 storres
            ##### Apply a different shrink factor according to
2254 212 storres
            #  the number of compliant polynomials.
2255 212 storres
            if len(ccReducedPolynomialsList) == 0:
2256 212 storres
                ub = lb + bw * noCoppersmithIntervalShrink
2257 212 storres
            else: # At least one compliant polynomial.
2258 212 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
2259 212 storres
            if ub > sdub:
2260 212 storres
                ub = sdub
2261 212 storres
            if lb == ub:
2262 212 storres
                raise Exception("Cant shrink interval \
2263 212 storres
                anymore to get Coppersmith condition.")
2264 212 storres
            nbw = 0
2265 212 storres
            continue
2266 212 storres
        #### We have at least two polynomials.
2267 212 storres
        #    Let us try to compute resultants.
2268 212 storres
        #    For each resultant computed, go for the solutions.
2269 212 storres
        ##### Build the pairs list.
2270 212 storres
        polyPairsList           = []
2271 212 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
2272 212 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
2273 212 storres
                                         len(ccReducedPolynomialsList)):
2274 212 storres
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
2275 212 storres
                                      ccReducedPolynomialsList[polyInnerIndex]))
2276 212 storres
        #### Actual root search.
2277 213 storres
        iRootsSet           = set()
2278 212 storres
        hasNonNullResultant = False
2279 212 storres
        for polyPair in polyPairsList:
2280 212 storres
            resultantsComputationTime   = cputime()
2281 212 storres
            currentResultantI = \
2282 212 storres
                slz_resultant(polyPair[0],
2283 212 storres
                              polyPair[1],
2284 212 storres
                              t)
2285 212 storres
            resultantsComputationsCount    += 1
2286 213 storres
            resultantsComputationsFullTime +=  \
2287 213 storres
                cputime(resultantsComputationTime)
2288 213 storres
            #### Function slz_resultant returns None both for None and O
2289 213 storres
            #    resultants.
2290 212 storres
            if currentResultantI is None:
2291 212 storres
                print "Nul resultant"
2292 212 storres
                continue # Next polyPair.
2293 213 storres
            ## We deleted the currentResultantI computation.
2294 213 storres
            #### We have a non null resultant. From now on, whatever this
2295 212 storres
            #    root search yields, no extra root search is necessary.
2296 213 storres
            hasNonNullResultant = True
2297 212 storres
            #### A constant resultant leads to no root. Root search is done.
2298 212 storres
            if currentResultantI.degree() < 1:
2299 212 storres
                print "Resultant is constant:", currentResultantI
2300 213 storres
                break # There is no root.
2301 213 storres
            #### Actual iroots computation.
2302 213 storres
            rootsComputationTime        = cputime()
2303 212 storres
            iRootsList = Zi(currentResultantI).roots()
2304 212 storres
            rootsComputationsCount      +=  1
2305 213 storres
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
2306 212 storres
            if len(iRootsList) == 0:
2307 212 storres
                print "No roots in \"i\"."
2308 212 storres
                break # No roots in i.
2309 213 storres
            else:
2310 213 storres
                for iRoot in iRootsList:
2311 213 storres
                    # A root is given as a (value, multiplicity) tuple.
2312 213 storres
                    iRootsSet.add(iRoot[0])
2313 213 storres
        # End loop for polyPair in polyParsList. We only loop again if a
2314 213 storres
        # None or zero resultant is found.
2315 212 storres
        #### Prepare for results for the current interval..
2316 212 storres
        intervalResultsList = []
2317 212 storres
        intervalResultsList.append((lb, ub))
2318 212 storres
        #### Check roots.
2319 212 storres
        rootsResultsList = []
2320 213 storres
        for iRoot in iRootsSet:
2321 212 storres
            specificRootResultsList = []
2322 213 storres
            failingBounds           = []
2323 212 storres
            # Root qualifies for modular equation, test it for hardness to round.
2324 213 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + iRoot) / toIntegerFactor)
2325 212 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
2326 212 storres
            #print scalingFunction
2327 212 storres
            scaledHardToRoundCaseAsFloat = \
2328 212 storres
                scalingFunction(hardToRoundCaseAsFloat)
2329 212 storres
            print "Candidate HTRNc at x =", \
2330 212 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
2331 212 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
2332 212 storres
                           function,
2333 212 storres
                           2^-(targetHardnessToRound),
2334 212 storres
                           RRR):
2335 212 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
2336 213 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
2337 212 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
2338 212 storres
                    print "Found in interval."
2339 212 storres
                else:
2340 212 storres
                    print "Found out of interval."
2341 213 storres
                # Check the i root is within the i bound.
2342 213 storres
                if abs(iRoot) > iBound:
2343 213 storres
                    print "IRoot", iRoot, "is out of bounds for modular equation."
2344 213 storres
                    print "i bound:", iBound
2345 213 storres
                    failingBounds.append('i')
2346 213 storres
                    failingBounds.append(iRoot)
2347 213 storres
                    failingBounds.append(iBound)
2348 212 storres
                if len(failingBounds) > 0:
2349 212 storres
                    specificRootResultsList.append(failingBounds)
2350 212 storres
            else: # From slz_is_htrn...
2351 212 storres
                print "is not an HTRN case."
2352 212 storres
            if len(specificRootResultsList) > 0:
2353 212 storres
                rootsResultsList.append(specificRootResultsList)
2354 212 storres
        if len(rootsResultsList) > 0:
2355 212 storres
            intervalResultsList.append(rootsResultsList)
2356 212 storres
        ### Check if a non null resultant was found. If not shrink the interval.
2357 212 storres
        if not hasNonNullResultant:
2358 212 storres
            print "Only null resultants for this reduction, shrinking interval."
2359 212 storres
            resultCondFailed      =  True
2360 212 storres
            resultCondFailedCount += 1
2361 212 storres
            ### Shrink interval for next iteration.
2362 212 storres
            ub = lb + bw * onlyNullResultantsShrink
2363 212 storres
            if ub > sdub:
2364 212 storres
                ub = sdub
2365 212 storres
            nbw = 0
2366 212 storres
            continue
2367 212 storres
        #### An intervalResultsList has at least the bounds.
2368 212 storres
        globalResultsList.append(intervalResultsList)
2369 212 storres
        #### Compute an incremented width for next upper bound, only
2370 212 storres
        #    if not Coppersmith condition nor resultant condition
2371 212 storres
        #    failed at the previous run.
2372 212 storres
        if not coppCondFailed and not resultCondFailed:
2373 212 storres
            nbw = noErrorIntervalStretch * bw
2374 212 storres
        else:
2375 212 storres
            nbw = bw
2376 212 storres
        ##### Reset the failure flags. They will be raised
2377 212 storres
        #     again if needed.
2378 212 storres
        coppCondFailed   = False
2379 212 storres
        resultCondFailed = False
2380 212 storres
        #### For next iteration (at end of loop)
2381 212 storres
        #print "nbw:", nbw
2382 212 storres
        lb  = ub
2383 212 storres
        ub += nbw
2384 212 storres
        if ub > sdub:
2385 212 storres
            ub = sdub
2386 212 storres
        print
2387 212 storres
    # End while True
2388 212 storres
    ## Main loop just ended.
2389 212 storres
    globalWallTime = walltime(wallTimeStart)
2390 212 storres
    globalCpuTime  = cputime(cpuTimeStart)
2391 212 storres
    ## Output results
2392 212 storres
    print ; print "Intervals and HTRNs" ; print
2393 212 storres
    for intervalResultsList in globalResultsList:
2394 222 storres
        intervalResultString = "[" + str(intervalResultsList[0][0]) +\
2395 222 storres
                               "," + str(intervalResultsList[0][1])  + "]"
2396 222 storres
        print intervalResultString,
2397 212 storres
        if len(intervalResultsList) > 1:
2398 212 storres
            rootsResultsList = intervalResultsList[1]
2399 222 storres
            specificRootResultIndex = 0
2400 212 storres
            for specificRootResultsList in rootsResultsList:
2401 222 storres
                if specificRootResultIndex == 0:
2402 222 storres
                    print "\t", specificRootResultsList[0],
2403 222 storres
                else:
2404 222 storres
                    print " " * len(intervalResultString), "\t", \
2405 222 storres
                          specificRootResultsList[0],
2406 212 storres
                if len(specificRootResultsList) > 1:
2407 222 storres
                    print specificRootResultsList[1]
2408 222 storres
                specificRootResultIndex += 1
2409 212 storres
        print ; print
2410 212 storres
    #print globalResultsList
2411 212 storres
    #
2412 212 storres
    print "Timers and counters"
2413 212 storres
    print
2414 212 storres
    print "Number of iterations:", iterCount
2415 212 storres
    print "Taylor condition failures:", taylCondFailedCount
2416 212 storres
    print "Coppersmith condition failures:", coppCondFailedCount
2417 212 storres
    print "Resultant condition failures:", resultCondFailedCount
2418 212 storres
    print "Iterations count: ", iterCount
2419 212 storres
    print "Number of intervals:", len(globalResultsList)
2420 212 storres
    print "Number of basis constructions:", basisConstructionsCount
2421 212 storres
    print "Total CPU time spent in basis constructions:", \
2422 212 storres
        basisConstructionsFullTime
2423 212 storres
    if basisConstructionsCount != 0:
2424 212 storres
        print "Average basis construction CPU time:", \
2425 212 storres
            basisConstructionsFullTime/basisConstructionsCount
2426 212 storres
    print "Number of reductions:", reductionsCount
2427 212 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
2428 212 storres
    if reductionsCount != 0:
2429 212 storres
        print "Average reduction CPU time:", \
2430 212 storres
            reductionsFullTime/reductionsCount
2431 212 storres
    print "Number of resultants computation rounds:", \
2432 212 storres
        resultantsComputationsCount
2433 212 storres
    print "Total CPU time spent in resultants computation rounds:", \
2434 212 storres
        resultantsComputationsFullTime
2435 212 storres
    if resultantsComputationsCount != 0:
2436 212 storres
        print "Average resultants computation round CPU time:", \
2437 212 storres
            resultantsComputationsFullTime/resultantsComputationsCount
2438 212 storres
    print "Number of root finding rounds:", rootsComputationsCount
2439 212 storres
    print "Total CPU time spent in roots finding rounds:", \
2440 212 storres
        rootsComputationsFullTime
2441 212 storres
    if rootsComputationsCount != 0:
2442 212 storres
        print "Average roots finding round CPU time:", \
2443 212 storres
            rootsComputationsFullTime/rootsComputationsCount
2444 212 storres
    print "Global Wall time:", globalWallTime
2445 212 storres
    print "Global CPU time:", globalCpuTime
2446 212 storres
    ## Output counters
2447 213 storres
# End srs_runSLZ-v04
2448 213 storres
2449 219 storres
def srs_run_SLZ_v05(inputFunction,
2450 219 storres
                    inputLowerBound,
2451 219 storres
                    inputUpperBound,
2452 219 storres
                    alpha,
2453 219 storres
                    degree,
2454 219 storres
                    precision,
2455 219 storres
                    emin,
2456 219 storres
                    emax,
2457 219 storres
                    targetHardnessToRound,
2458 219 storres
                    debug = False):
2459 219 storres
    """
2460 219 storres
    Changes from V4:
2461 219 storres
        Approximation polynomial has coefficients rounded.
2462 219 storres
    Changes from V3:
2463 219 storres
        Root search is changed again:
2464 219 storres
            - only resultants in i are computed;
2465 219 storres
            - roots in i are searched for;
2466 219 storres
            - if any, they are tested for hardness-to-round.
2467 219 storres
    Changes from V2:
2468 219 storres
        Root search is changed:
2469 219 storres
            - we compute the resultants in i and in t;
2470 219 storres
            - we compute the roots set of each of these resultants;
2471 219 storres
            - we combine all the possible pairs between the two sets;
2472 219 storres
            - we check these pairs in polynomials for correctness.
2473 219 storres
    Changes from V1:
2474 219 storres
        1- check for roots as soon as a resultant is computed;
2475 219 storres
        2- once a non null resultant is found, check for roots;
2476 219 storres
        3- constant resultant == no root.
2477 219 storres
    """
2478 219 storres
2479 219 storres
    if debug:
2480 219 storres
        print "Function                :", inputFunction
2481 219 storres
        print "Lower bound             :", inputLowerBound
2482 219 storres
        print "Upper bounds            :", inputUpperBound
2483 219 storres
        print "Alpha                   :", alpha
2484 219 storres
        print "Degree                  :", degree
2485 219 storres
        print "Precision               :", precision
2486 219 storres
        print "Emin                    :", emin
2487 219 storres
        print "Emax                    :", emax
2488 219 storres
        print "Target hardness-to-round:", targetHardnessToRound
2489 219 storres
        print
2490 219 storres
    ## Important constants.
2491 219 storres
    ### Stretch the interval if no error happens.
2492 219 storres
    noErrorIntervalStretch = 1 + 2^(-5)
2493 219 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
2494 219 storres
    #   by the following factor.
2495 219 storres
    noCoppersmithIntervalShrink = 1/2
2496 219 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
2497 219 storres
    #   shrink the interval by the following factor.
2498 219 storres
    oneCoppersmithIntervalShrink = 3/4
2499 219 storres
    #### If only null resultants are found, shrink the interval by the
2500 219 storres
    #    following factor.
2501 219 storres
    onlyNullResultantsShrink     = 3/4
2502 219 storres
    ## Structures.
2503 219 storres
    RRR         = RealField(precision)
2504 219 storres
    RRIF        = RealIntervalField(precision)
2505 219 storres
    ## Converting input bound into the "right" field.
2506 219 storres
    lowerBound = RRR(inputLowerBound)
2507 219 storres
    upperBound = RRR(inputUpperBound)
2508 219 storres
    ## Before going any further, check domain and image binade conditions.
2509 219 storres
    print inputFunction(1).n()
2510 219 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
2511 219 storres
    if output is None:
2512 219 storres
        print "Invalid domain/image binades. Domain:",\
2513 219 storres
        lowerBound, upperBound, "Images:", \
2514 219 storres
        inputFunction(lowerBound), inputFunction(upperBound)
2515 219 storres
        raise Exception("Invalid domain/image binades.")
2516 219 storres
    lb = output[0] ; ub = output[1]
2517 219 storres
    if lb != lowerBound or ub != upperBound:
2518 219 storres
        print "lb:", lb, " - ub:", ub
2519 219 storres
        print "Invalid domain/image binades. Domain:",\
2520 219 storres
        lowerBound, upperBound, "Images:", \
2521 219 storres
        inputFunction(lowerBound), inputFunction(upperBound)
2522 219 storres
        raise Exception("Invalid domain/image binades.")
2523 219 storres
    #
2524 219 storres
    ## Progam initialization
2525 219 storres
    ### Approximation polynomial accuracy and hardness to round.
2526 219 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
2527 219 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
2528 219 storres
    ### Significand to integer conversion ratio.
2529 219 storres
    toIntegerFactor           = 2^(precision-1)
2530 219 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
2531 219 storres
    ### Variables and rings for polynomials and root searching.
2532 219 storres
    i=var('i')
2533 219 storres
    t=var('t')
2534 219 storres
    inputFunctionVariable = inputFunction.variables()[0]
2535 219 storres
    function = inputFunction.subs({inputFunctionVariable:i})
2536 219 storres
    #  Polynomial Rings over the integers, for root finding.
2537 219 storres
    Zi = ZZ[i]
2538 219 storres
    Zt = ZZ[t]
2539 219 storres
    Zit = ZZ[i,t]
2540 219 storres
    ## Number of iterations limit.
2541 219 storres
    maxIter = 100000
2542 219 storres
    #
2543 231 storres
    ## Set the variable name in Sollya.
2544 231 storres
    pobyso_name_free_variable_sa_so(str(function.variables()[0]))
2545 219 storres
    ## Compute the scaled function and the degree, in their Sollya version
2546 219 storres
    #  once for all.
2547 219 storres
    (scaledf, sdlb, sdub, silb, siub) = \
2548 219 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
2549 219 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
2550 231 storres
    #print "Scaled bounds:", sdlb, sdub
2551 219 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
2552 219 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
2553 219 storres
    #
2554 219 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
2555 219 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
2556 219 storres
    (unscalingFunction, scalingFunction) = \
2557 219 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
2558 219 storres
    #print scalingFunction, unscalingFunction
2559 219 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
2560 219 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
2561 219 storres
    if internalSollyaPrec < 192:
2562 219 storres
        internalSollyaPrec = 192
2563 219 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
2564 219 storres
    print "Sollya internal precision:", internalSollyaPrec
2565 219 storres
    ## Some variables.
2566 219 storres
    ### General variables
2567 219 storres
    lb                  = sdlb
2568 219 storres
    ub                  = sdub
2569 219 storres
    nbw                 = 0
2570 219 storres
    intervalUlp         = ub.ulp()
2571 219 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
2572 219 storres
    ic                  = 0
2573 219 storres
    icAsInt             = 0    # Set from ic.
2574 219 storres
    solutionsSet        = set()
2575 219 storres
    tsErrorWidth        = []
2576 219 storres
    csErrorVectors      = []
2577 219 storres
    csVectorsResultants = []
2578 219 storres
    floatP              = 0  # Taylor polynomial.
2579 219 storres
    floatPcv            = 0  # Ditto with variable change.
2580 219 storres
    intvl               = "" # Taylor interval
2581 219 storres
    terr                = 0  # Taylor error.
2582 219 storres
    iterCount = 0
2583 219 storres
    htrnSet = set()
2584 219 storres
    ### Timers and counters.
2585 219 storres
    wallTimeStart                   = 0
2586 219 storres
    cpuTimeStart                    = 0
2587 219 storres
    taylCondFailedCount             = 0
2588 219 storres
    coppCondFailedCount             = 0
2589 219 storres
    resultCondFailedCount           = 0
2590 219 storres
    coppCondFailed                  = False
2591 219 storres
    resultCondFailed                = False
2592 219 storres
    globalResultsList               = []
2593 219 storres
    basisConstructionsCount         = 0
2594 219 storres
    basisConstructionsFullTime      = 0
2595 219 storres
    basisConstructionTime           = 0
2596 219 storres
    reductionsCount                 = 0
2597 219 storres
    reductionsFullTime              = 0
2598 219 storres
    reductionTime                   = 0
2599 219 storres
    resultantsComputationsCount     = 0
2600 219 storres
    resultantsComputationsFullTime  = 0
2601 219 storres
    resultantsComputationTime       = 0
2602 219 storres
    rootsComputationsCount          = 0
2603 219 storres
    rootsComputationsFullTime       = 0
2604 219 storres
    rootsComputationTime            = 0
2605 219 storres
    print
2606 219 storres
    ## Global times are started here.
2607 219 storres
    wallTimeStart                   = walltime()
2608 219 storres
    cpuTimeStart                    = cputime()
2609 219 storres
    ## Main loop.
2610 219 storres
    while True:
2611 219 storres
        if lb >= sdub:
2612 219 storres
            print "Lower bound reached upper bound."
2613 219 storres
            break
2614 219 storres
        if iterCount == maxIter:
2615 219 storres
            print "Reached maxIter. Aborting"
2616 219 storres
            break
2617 219 storres
        iterCount += 1
2618 219 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
2619 219 storres
            "log2(numbers)."
2620 219 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
2621 219 storres
        prceSo = slz_compute_polynomial_and_interval_01(scaledfSo,
2622 219 storres
                                                        degreeSo,
2623 219 storres
                                                        lb,
2624 219 storres
                                                        ub,
2625 219 storres
                                                        polyApproxAccur)
2626 230 storres
        if debug:
2627 230 storres
            print "Approximation polynomial computed."
2628 225 storres
        if prceSo is None:
2629 225 storres
            raise Exception("Could not compute an approximation polynomial.")
2630 219 storres
        ### Convert back the data into Sage space.
2631 219 storres
        (floatP, floatPcv, intvl, ic, terr) = \
2632 219 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
2633 219 storres
                                                 prceSo[1], prceSo[2],
2634 219 storres
                                                 prceSo[3]))
2635 219 storres
        intvl = RRIF(intvl)
2636 219 storres
        ## Clean-up Sollya stuff.
2637 219 storres
        for elem in prceSo:
2638 219 storres
            sollya_lib_clear_obj(elem)
2639 219 storres
        #print  floatP, floatPcv, intvl, ic, terr
2640 219 storres
        #print floatP
2641 219 storres
        #print intvl.endpoints()[0].n(), \
2642 219 storres
        #      ic.n(),
2643 219 storres
        #intvl.endpoints()[1].n()
2644 219 storres
        ### Check returned data.
2645 219 storres
        #### Is approximation error OK?
2646 219 storres
        if terr > polyApproxAccur:
2647 219 storres
            exceptionErrorMess  = \
2648 219 storres
                "Approximation failed - computed error:" + \
2649 219 storres
                str(terr) + " - target error: "
2650 219 storres
            exceptionErrorMess += \
2651 219 storres
                str(polyApproxAccur) + ". Aborting!"
2652 219 storres
            raise Exception(exceptionErrorMess)
2653 219 storres
        #### Is lower bound OK?
2654 219 storres
        if lb != intvl.endpoints()[0]:
2655 219 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
2656 219 storres
                               str(lb) + ". Aborting!"
2657 219 storres
            raise Exception(exceptionErrorMess)
2658 219 storres
        #### Set upper bound.
2659 219 storres
        if ub > intvl.endpoints()[1]:
2660 219 storres
            ub = intvl.endpoints()[1]
2661 219 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
2662 219 storres
            "log2(numbers)."
2663 219 storres
            taylCondFailedCount += 1
2664 219 storres
        #### Is interval not degenerate?
2665 219 storres
        if lb >= ub:
2666 219 storres
            exceptionErrorMess = "Degenerate interval: " + \
2667 219 storres
                                "lowerBound(" + str(lb) +\
2668 219 storres
                                ")>= upperBound(" + str(ub) + \
2669 219 storres
                                "). Aborting!"
2670 219 storres
            raise Exception(exceptionErrorMess)
2671 219 storres
        #### Is interval center ok?
2672 219 storres
        if ic <= lb or ic >= ub:
2673 219 storres
            exceptionErrorMess =  "Invalid interval center for " + \
2674 219 storres
                                str(lb) + ',' + str(ic) + ',' +  \
2675 219 storres
                                str(ub) + ". Aborting!"
2676 219 storres
            raise Exception(exceptionErrorMess)
2677 219 storres
        ##### Current interval width and reset future interval width.
2678 219 storres
        bw = ub - lb
2679 219 storres
        nbw = 0
2680 219 storres
        icAsInt = int(ic * toIntegerFactor)
2681 219 storres
        #### The following ratio is always >= 1. In case we may want to
2682 219 storres
        #    enlarge the interval
2683 219 storres
        curTaylErrRat = polyApproxAccur / terr
2684 219 storres
        ### Make the  integral transformations.
2685 219 storres
        #### Bounds and interval center.
2686 219 storres
        intIc = int(ic * toIntegerFactor)
2687 219 storres
        intLb = int(lb * toIntegerFactor) - intIc
2688 219 storres
        intUb = int(ub * toIntegerFactor) - intIc
2689 219 storres
        #
2690 219 storres
        #### Polynomials
2691 219 storres
        basisConstructionTime         = cputime()
2692 219 storres
        ##### To a polynomial with rational coefficients with rational arguments
2693 219 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
2694 219 storres
        ##### To a polynomial with rational coefficients with integer arguments
2695 219 storres
        ratIntP = \
2696 219 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
2697 219 storres
        #####  Ultimately a multivariate polynomial with integer coefficients
2698 219 storres
        #      with integer arguments.
2699 219 storres
        coppersmithTuple = \
2700 219 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
2701 219 storres
                                                        precision,
2702 219 storres
                                                        targetHardnessToRound,
2703 219 storres
                                                        i, t)
2704 219 storres
        #### Recover Coppersmith information.
2705 219 storres
        intIntP = coppersmithTuple[0]
2706 219 storres
        N = coppersmithTuple[1]
2707 219 storres
        nAtAlpha = N^alpha
2708 219 storres
        tBound = coppersmithTuple[2]
2709 219 storres
        leastCommonMultiple = coppersmithTuple[3]
2710 219 storres
        iBound = max(abs(intLb),abs(intUb))
2711 219 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
2712 219 storres
        basisConstructionsCount           += 1
2713 224 storres
        #### Compute the matrix to reduce for debug purpose. Otherwise
2714 224 storres
        #    slz_compute_coppersmith_reduced_polynomials does the job
2715 224 storres
        #    invisibly.
2716 224 storres
        if debug:
2717 224 storres
            matrixToReduce = slz_compute_initial_lattice_matrix(intIntP,
2718 224 storres
                                                                alpha,
2719 224 storres
                                                                N,
2720 224 storres
                                                                iBound,
2721 224 storres
                                                                tBound)
2722 224 storres
            maxNorm     = 0
2723 224 storres
            latticeSize = 0
2724 224 storres
            matrixFile = file('/tmp/matrixToReduce.txt', 'w')
2725 224 storres
            for row in matrixToReduce.rows():
2726 224 storres
                currentNorm = row.norm()
2727 224 storres
                if currentNorm > maxNorm:
2728 224 storres
                    maxNorm = currentNorm
2729 224 storres
                latticeSize += 1
2730 224 storres
                for elem in row:
2731 224 storres
                    matrixFile.write(elem.str(base=2) + ",")
2732 224 storres
                matrixFile.write("\n")
2733 224 storres
            #matrixFile.write(matrixToReduce.str(radix="2") + "\n")
2734 224 storres
            matrixFile.close()
2735 224 storres
            #### We use here binary length as defined in LLL princepts.
2736 224 storres
            binaryLength = latticeSize * log(maxNorm)
2737 224 storres
            print "Binary length:", binaryLength.n()
2738 224 storres
            raise Exception("Deliberate stop here.")
2739 224 storres
        # End if debug
2740 219 storres
        reductionTime                     = cputime()
2741 219 storres
        #### Compute the reduced polynomials.
2742 230 storres
        print "Starting reduction..."
2743 219 storres
        ccReducedPolynomialsList =  \
2744 219 storres
                slz_compute_coppersmith_reduced_polynomials(intIntP,
2745 219 storres
                                                            alpha,
2746 219 storres
                                                            N,
2747 219 storres
                                                            iBound,
2748 219 storres
                                                            tBound)
2749 230 storres
        print "...reduction accomplished in", cputime(reductionTime), "s."
2750 219 storres
        if ccReducedPolynomialsList is None:
2751 219 storres
            raise Exception("Reduction failed.")
2752 219 storres
        reductionsFullTime    += cputime(reductionTime)
2753 219 storres
        reductionsCount       += 1
2754 219 storres
        if len(ccReducedPolynomialsList) < 2:
2755 219 storres
            print "Nothing to form resultants with."
2756 219 storres
            print
2757 219 storres
            coppCondFailedCount += 1
2758 219 storres
            coppCondFailed = True
2759 219 storres
            ##### Apply a different shrink factor according to
2760 219 storres
            #  the number of compliant polynomials.
2761 219 storres
            if len(ccReducedPolynomialsList) == 0:
2762 219 storres
                ub = lb + bw * noCoppersmithIntervalShrink
2763 219 storres
            else: # At least one compliant polynomial.
2764 219 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
2765 219 storres
            if ub > sdub:
2766 219 storres
                ub = sdub
2767 219 storres
            if lb == ub:
2768 219 storres
                raise Exception("Cant shrink interval \
2769 219 storres
                anymore to get Coppersmith condition.")
2770 219 storres
            nbw = 0
2771 219 storres
            continue
2772 219 storres
        #### We have at least two polynomials.
2773 219 storres
        #    Let us try to compute resultants.
2774 219 storres
        #    For each resultant computed, go for the solutions.
2775 219 storres
        ##### Build the pairs list.
2776 219 storres
        polyPairsList           = []
2777 219 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
2778 219 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
2779 219 storres
                                         len(ccReducedPolynomialsList)):
2780 219 storres
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
2781 219 storres
                                      ccReducedPolynomialsList[polyInnerIndex]))
2782 219 storres
        #### Actual root search.
2783 219 storres
        iRootsSet           = set()
2784 219 storres
        hasNonNullResultant = False
2785 219 storres
        for polyPair in polyPairsList:
2786 219 storres
            resultantsComputationTime   = cputime()
2787 219 storres
            currentResultantI = \
2788 219 storres
                slz_resultant(polyPair[0],
2789 219 storres
                              polyPair[1],
2790 219 storres
                              t)
2791 219 storres
            resultantsComputationsCount    += 1
2792 219 storres
            resultantsComputationsFullTime +=  \
2793 219 storres
                cputime(resultantsComputationTime)
2794 219 storres
            #### Function slz_resultant returns None both for None and O
2795 219 storres
            #    resultants.
2796 219 storres
            if currentResultantI is None:
2797 219 storres
                print "Nul resultant"
2798 219 storres
                continue # Next polyPair.
2799 219 storres
            ## We deleted the currentResultantI computation.
2800 219 storres
            #### We have a non null resultant. From now on, whatever this
2801 219 storres
            #    root search yields, no extra root search is necessary.
2802 219 storres
            hasNonNullResultant = True
2803 219 storres
            #### A constant resultant leads to no root. Root search is done.
2804 219 storres
            if currentResultantI.degree() < 1:
2805 219 storres
                print "Resultant is constant:", currentResultantI
2806 219 storres
                break # There is no root.
2807 219 storres
            #### Actual iroots computation.
2808 219 storres
            rootsComputationTime        = cputime()
2809 219 storres
            iRootsList = Zi(currentResultantI).roots()
2810 219 storres
            rootsComputationsCount      +=  1
2811 219 storres
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
2812 219 storres
            if len(iRootsList) == 0:
2813 219 storres
                print "No roots in \"i\"."
2814 219 storres
                break # No roots in i.
2815 219 storres
            else:
2816 219 storres
                for iRoot in iRootsList:
2817 219 storres
                    # A root is given as a (value, multiplicity) tuple.
2818 219 storres
                    iRootsSet.add(iRoot[0])
2819 219 storres
        # End loop for polyPair in polyParsList. We only loop again if a
2820 219 storres
        # None or zero resultant is found.
2821 219 storres
        #### Prepare for results for the current interval..
2822 219 storres
        intervalResultsList = []
2823 219 storres
        intervalResultsList.append((lb, ub))
2824 219 storres
        #### Check roots.
2825 219 storres
        rootsResultsList = []
2826 219 storres
        for iRoot in iRootsSet:
2827 219 storres
            specificRootResultsList = []
2828 219 storres
            failingBounds           = []
2829 219 storres
            # Root qualifies for modular equation, test it for hardness to round.
2830 219 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + iRoot) / toIntegerFactor)
2831 219 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
2832 219 storres
            #print scalingFunction
2833 219 storres
            scaledHardToRoundCaseAsFloat = \
2834 219 storres
                scalingFunction(hardToRoundCaseAsFloat)
2835 219 storres
            print "Candidate HTRNc at x =", \
2836 219 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
2837 219 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
2838 219 storres
                           function,
2839 219 storres
                           2^-(targetHardnessToRound),
2840 219 storres
                           RRR):
2841 219 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
2842 219 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
2843 219 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
2844 219 storres
                    print "Found in interval."
2845 219 storres
                else:
2846 219 storres
                    print "Found out of interval."
2847 219 storres
                # Check the i root is within the i bound.
2848 219 storres
                if abs(iRoot) > iBound:
2849 219 storres
                    print "IRoot", iRoot, "is out of bounds for modular equation."
2850 219 storres
                    print "i bound:", iBound
2851 219 storres
                    failingBounds.append('i')
2852 219 storres
                    failingBounds.append(iRoot)
2853 219 storres
                    failingBounds.append(iBound)
2854 219 storres
                if len(failingBounds) > 0:
2855 219 storres
                    specificRootResultsList.append(failingBounds)
2856 219 storres
            else: # From slz_is_htrn...
2857 219 storres
                print "is not an HTRN case."
2858 219 storres
            if len(specificRootResultsList) > 0:
2859 219 storres
                rootsResultsList.append(specificRootResultsList)
2860 219 storres
        if len(rootsResultsList) > 0:
2861 219 storres
            intervalResultsList.append(rootsResultsList)
2862 219 storres
        ### Check if a non null resultant was found. If not shrink the interval.
2863 219 storres
        if not hasNonNullResultant:
2864 219 storres
            print "Only null resultants for this reduction, shrinking interval."
2865 219 storres
            resultCondFailed      =  True
2866 219 storres
            resultCondFailedCount += 1
2867 219 storres
            ### Shrink interval for next iteration.
2868 219 storres
            ub = lb + bw * onlyNullResultantsShrink
2869 219 storres
            if ub > sdub:
2870 219 storres
                ub = sdub
2871 219 storres
            nbw = 0
2872 219 storres
            continue
2873 219 storres
        #### An intervalResultsList has at least the bounds.
2874 219 storres
        globalResultsList.append(intervalResultsList)
2875 219 storres
        #### Compute an incremented width for next upper bound, only
2876 219 storres
        #    if not Coppersmith condition nor resultant condition
2877 219 storres
        #    failed at the previous run.
2878 219 storres
        if not coppCondFailed and not resultCondFailed:
2879 219 storres
            nbw = noErrorIntervalStretch * bw
2880 219 storres
        else:
2881 219 storres
            nbw = bw
2882 219 storres
        ##### Reset the failure flags. They will be raised
2883 219 storres
        #     again if needed.
2884 219 storres
        coppCondFailed   = False
2885 219 storres
        resultCondFailed = False
2886 219 storres
        #### For next iteration (at end of loop)
2887 219 storres
        #print "nbw:", nbw
2888 219 storres
        lb  = ub
2889 219 storres
        ub += nbw
2890 219 storres
        if ub > sdub:
2891 219 storres
            ub = sdub
2892 219 storres
        print
2893 219 storres
    # End while True
2894 219 storres
    ## Main loop just ended.
2895 219 storres
    globalWallTime = walltime(wallTimeStart)
2896 219 storres
    globalCpuTime  = cputime(cpuTimeStart)
2897 219 storres
    ## Output results
2898 219 storres
    print ; print "Intervals and HTRNs" ; print
2899 219 storres
    for intervalResultsList in globalResultsList:
2900 222 storres
        intervalResultString = "[" + str(intervalResultsList[0][0]) +\
2901 222 storres
                               "," + str(intervalResultsList[0][1])  + "]"
2902 222 storres
        print intervalResultString,
2903 219 storres
        if len(intervalResultsList) > 1:
2904 219 storres
            rootsResultsList = intervalResultsList[1]
2905 222 storres
            specificRootResultIndex = 0
2906 219 storres
            for specificRootResultsList in rootsResultsList:
2907 222 storres
                if specificRootResultIndex == 0:
2908 222 storres
                    print "\t", specificRootResultsList[0],
2909 222 storres
                else:
2910 222 storres
                    print " " * len(intervalResultString), "\t", \
2911 222 storres
                          specificRootResultsList[0],
2912 219 storres
                if len(specificRootResultsList) > 1:
2913 222 storres
                    print specificRootResultsList[1]
2914 222 storres
                specificRootResultIndex += 1
2915 219 storres
        print ; print
2916 219 storres
    #print globalResultsList
2917 219 storres
    #
2918 219 storres
    print "Timers and counters"
2919 219 storres
    print
2920 219 storres
    print "Number of iterations:", iterCount
2921 219 storres
    print "Taylor condition failures:", taylCondFailedCount
2922 219 storres
    print "Coppersmith condition failures:", coppCondFailedCount
2923 219 storres
    print "Resultant condition failures:", resultCondFailedCount
2924 219 storres
    print "Iterations count: ", iterCount
2925 219 storres
    print "Number of intervals:", len(globalResultsList)
2926 219 storres
    print "Number of basis constructions:", basisConstructionsCount
2927 219 storres
    print "Total CPU time spent in basis constructions:", \
2928 219 storres
        basisConstructionsFullTime
2929 219 storres
    if basisConstructionsCount != 0:
2930 219 storres
        print "Average basis construction CPU time:", \
2931 219 storres
            basisConstructionsFullTime/basisConstructionsCount
2932 219 storres
    print "Number of reductions:", reductionsCount
2933 219 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
2934 219 storres
    if reductionsCount != 0:
2935 219 storres
        print "Average reduction CPU time:", \
2936 219 storres
            reductionsFullTime/reductionsCount
2937 219 storres
    print "Number of resultants computation rounds:", \
2938 219 storres
        resultantsComputationsCount
2939 219 storres
    print "Total CPU time spent in resultants computation rounds:", \
2940 219 storres
        resultantsComputationsFullTime
2941 219 storres
    if resultantsComputationsCount != 0:
2942 219 storres
        print "Average resultants computation round CPU time:", \
2943 219 storres
            resultantsComputationsFullTime/resultantsComputationsCount
2944 219 storres
    print "Number of root finding rounds:", rootsComputationsCount
2945 219 storres
    print "Total CPU time spent in roots finding rounds:", \
2946 219 storres
        rootsComputationsFullTime
2947 219 storres
    if rootsComputationsCount != 0:
2948 219 storres
        print "Average roots finding round CPU time:", \
2949 219 storres
            rootsComputationsFullTime/rootsComputationsCount
2950 219 storres
    print "Global Wall time:", globalWallTime
2951 219 storres
    print "Global CPU time:", globalCpuTime
2952 219 storres
    ## Output counters
2953 219 storres
# End srs_runSLZ-v05
2954 244 storres
#
2955 244 storres
def srs_run_SLZ_v05_gram(inputFunction,
2956 244 storres
                         inputLowerBound,
2957 244 storres
                         inputUpperBound,
2958 244 storres
                         alpha,
2959 244 storres
                         degree,
2960 244 storres
                         precision,
2961 244 storres
                         emin,
2962 244 storres
                         emax,
2963 244 storres
                         targetHardnessToRound,
2964 244 storres
                         debug = False):
2965 244 storres
    """
2966 244 storres
    changes from plain V5:
2967 244 storres
        Uses Pari LLL reduction from the Gram matrix.
2968 244 storres
    Changes from V4:
2969 244 storres
        Approximation polynomial has coefficients rounded.
2970 244 storres
    Changes from V3:
2971 244 storres
        Root search is changed again:
2972 244 storres
            - only resultants in i are computed;
2973 244 storres
            - roots in i are searched for;
2974 244 storres
            - if any, they are tested for hardness-to-round.
2975 244 storres
    Changes from V2:
2976 244 storres
        Root search is changed:
2977 244 storres
            - we compute the resultants in i and in t;
2978 244 storres
            - we compute the roots set of each of these resultants;
2979 244 storres
            - we combine all the possible pairs between the two sets;
2980 244 storres
            - we check these pairs in polynomials for correctness.
2981 244 storres
    Changes from V1:
2982 244 storres
        1- check for roots as soon as a resultant is computed;
2983 244 storres
        2- once a non null resultant is found, check for roots;
2984 244 storres
        3- constant resultant == no root.
2985 244 storres
    """
2986 222 storres
2987 244 storres
    if debug:
2988 244 storres
        print "Function                :", inputFunction
2989 244 storres
        print "Lower bound             :", inputLowerBound
2990 244 storres
        print "Upper bounds            :", inputUpperBound
2991 244 storres
        print "Alpha                   :", alpha
2992 244 storres
        print "Degree                  :", degree
2993 244 storres
        print "Precision               :", precision
2994 244 storres
        print "Emin                    :", emin
2995 244 storres
        print "Emax                    :", emax
2996 244 storres
        print "Target hardness-to-round:", targetHardnessToRound
2997 244 storres
        print
2998 244 storres
    ## Important constants.
2999 244 storres
    ### Stretch the interval if no error happens.
3000 244 storres
    noErrorIntervalStretch = 1 + 2^(-5)
3001 244 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
3002 244 storres
    #   by the following factor.
3003 244 storres
    noCoppersmithIntervalShrink = 1/2
3004 244 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
3005 244 storres
    #   shrink the interval by the following factor.
3006 244 storres
    oneCoppersmithIntervalShrink = 3/4
3007 244 storres
    #### If only null resultants are found, shrink the interval by the
3008 244 storres
    #    following factor.
3009 244 storres
    onlyNullResultantsShrink     = 3/4
3010 244 storres
    ## Structures.
3011 244 storres
    RRR         = RealField(precision)
3012 244 storres
    RRIF        = RealIntervalField(precision)
3013 244 storres
    ## Converting input bound into the "right" field.
3014 244 storres
    lowerBound = RRR(inputLowerBound)
3015 244 storres
    upperBound = RRR(inputUpperBound)
3016 244 storres
    ## Before going any further, check domain and image binade conditions.
3017 244 storres
    print inputFunction(1).n()
3018 244 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
3019 244 storres
    if output is None:
3020 244 storres
        print "Invalid domain/image binades. Domain:",\
3021 244 storres
        lowerBound, upperBound, "Images:", \
3022 244 storres
        inputFunction(lowerBound), inputFunction(upperBound)
3023 244 storres
        raise Exception("Invalid domain/image binades.")
3024 244 storres
    lb = output[0] ; ub = output[1]
3025 244 storres
    if lb != lowerBound or ub != upperBound:
3026 244 storres
        print "lb:", lb, " - ub:", ub
3027 244 storres
        print "Invalid domain/image binades. Domain:",\
3028 244 storres
        lowerBound, upperBound, "Images:", \
3029 244 storres
        inputFunction(lowerBound), inputFunction(upperBound)
3030 244 storres
        raise Exception("Invalid domain/image binades.")
3031 244 storres
    #
3032 244 storres
    ## Progam initialization
3033 244 storres
    ### Approximation polynomial accuracy and hardness to round.
3034 244 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
3035 244 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
3036 244 storres
    ### Significand to integer conversion ratio.
3037 244 storres
    toIntegerFactor           = 2^(precision-1)
3038 244 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
3039 244 storres
    ### Variables and rings for polynomials and root searching.
3040 244 storres
    i=var('i')
3041 244 storres
    t=var('t')
3042 244 storres
    inputFunctionVariable = inputFunction.variables()[0]
3043 244 storres
    function = inputFunction.subs({inputFunctionVariable:i})
3044 244 storres
    #  Polynomial Rings over the integers, for root finding.
3045 244 storres
    Zi = ZZ[i]
3046 244 storres
    Zt = ZZ[t]
3047 244 storres
    Zit = ZZ[i,t]
3048 244 storres
    ## Number of iterations limit.
3049 244 storres
    maxIter = 100000
3050 244 storres
    #
3051 244 storres
    ## Set the variable name in Sollya.
3052 244 storres
    pobyso_name_free_variable_sa_so(str(function.variables()[0]))
3053 244 storres
    ## Compute the scaled function and the degree, in their Sollya version
3054 244 storres
    #  once for all.
3055 244 storres
    (scaledf, sdlb, sdub, silb, siub) = \
3056 244 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
3057 244 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
3058 244 storres
    #print "Scaled bounds:", sdlb, sdub
3059 244 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
3060 244 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
3061 244 storres
    #
3062 244 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
3063 244 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
3064 244 storres
    (unscalingFunction, scalingFunction) = \
3065 244 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
3066 244 storres
    #print scalingFunction, unscalingFunction
3067 244 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
3068 244 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
3069 244 storres
    if internalSollyaPrec < 192:
3070 244 storres
        internalSollyaPrec = 192
3071 244 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
3072 244 storres
    print "Sollya internal precision:", internalSollyaPrec
3073 244 storres
    ## Some variables.
3074 244 storres
    ### General variables
3075 244 storres
    lb                  = sdlb
3076 244 storres
    ub                  = sdub
3077 244 storres
    nbw                 = 0
3078 244 storres
    intervalUlp         = ub.ulp()
3079 244 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
3080 244 storres
    ic                  = 0
3081 244 storres
    icAsInt             = 0    # Set from ic.
3082 244 storres
    solutionsSet        = set()
3083 244 storres
    tsErrorWidth        = []
3084 244 storres
    csErrorVectors      = []
3085 244 storres
    csVectorsResultants = []
3086 244 storres
    floatP              = 0  # Taylor polynomial.
3087 244 storres
    floatPcv            = 0  # Ditto with variable change.
3088 244 storres
    intvl               = "" # Taylor interval
3089 244 storres
    terr                = 0  # Taylor error.
3090 244 storres
    iterCount = 0
3091 244 storres
    htrnSet = set()
3092 244 storres
    ### Timers and counters.
3093 244 storres
    wallTimeStart                   = 0
3094 244 storres
    cpuTimeStart                    = 0
3095 244 storres
    taylCondFailedCount             = 0
3096 244 storres
    coppCondFailedCount             = 0
3097 244 storres
    resultCondFailedCount           = 0
3098 244 storres
    coppCondFailed                  = False
3099 244 storres
    resultCondFailed                = False
3100 244 storres
    globalResultsList               = []
3101 244 storres
    basisConstructionsCount         = 0
3102 244 storres
    basisConstructionsFullTime      = 0
3103 244 storres
    basisConstructionTime           = 0
3104 244 storres
    reductionsCount                 = 0
3105 244 storres
    reductionsFullTime              = 0
3106 244 storres
    reductionTime                   = 0
3107 244 storres
    resultantsComputationsCount     = 0
3108 244 storres
    resultantsComputationsFullTime  = 0
3109 244 storres
    resultantsComputationTime       = 0
3110 244 storres
    rootsComputationsCount          = 0
3111 244 storres
    rootsComputationsFullTime       = 0
3112 244 storres
    rootsComputationTime            = 0
3113 244 storres
    print
3114 244 storres
    ## Global times are started here.
3115 244 storres
    wallTimeStart                   = walltime()
3116 244 storres
    cpuTimeStart                    = cputime()
3117 244 storres
    ## Main loop.
3118 244 storres
    while True:
3119 244 storres
        if lb >= sdub:
3120 244 storres
            print "Lower bound reached upper bound."
3121 244 storres
            break
3122 244 storres
        if iterCount == maxIter:
3123 244 storres
            print "Reached maxIter. Aborting"
3124 244 storres
            break
3125 244 storres
        iterCount += 1
3126 244 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
3127 244 storres
            "log2(numbers)."
3128 244 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
3129 244 storres
        prceSo = slz_compute_polynomial_and_interval_01(scaledfSo,
3130 244 storres
                                                        degreeSo,
3131 244 storres
                                                        lb,
3132 244 storres
                                                        ub,
3133 244 storres
                                                        polyApproxAccur)
3134 244 storres
        if debug:
3135 244 storres
            print "Approximation polynomial computed."
3136 244 storres
        if prceSo is None:
3137 244 storres
            raise Exception("Could not compute an approximation polynomial.")
3138 244 storres
        ### Convert back the data into Sage space.
3139 244 storres
        (floatP, floatPcv, intvl, ic, terr) = \
3140 244 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
3141 244 storres
                                                 prceSo[1], prceSo[2],
3142 244 storres
                                                 prceSo[3]))
3143 244 storres
        intvl = RRIF(intvl)
3144 244 storres
        ## Clean-up Sollya stuff.
3145 244 storres
        for elem in prceSo:
3146 244 storres
            sollya_lib_clear_obj(elem)
3147 244 storres
        #print  floatP, floatPcv, intvl, ic, terr
3148 244 storres
        #print floatP
3149 244 storres
        #print intvl.endpoints()[0].n(), \
3150 244 storres
        #      ic.n(),
3151 244 storres
        #intvl.endpoints()[1].n()
3152 244 storres
        ### Check returned data.
3153 244 storres
        #### Is approximation error OK?
3154 244 storres
        if terr > polyApproxAccur:
3155 244 storres
            exceptionErrorMess  = \
3156 244 storres
                "Approximation failed - computed error:" + \
3157 244 storres
                str(terr) + " - target error: "
3158 244 storres
            exceptionErrorMess += \
3159 244 storres
                str(polyApproxAccur) + ". Aborting!"
3160 244 storres
            raise Exception(exceptionErrorMess)
3161 244 storres
        #### Is lower bound OK?
3162 244 storres
        if lb != intvl.endpoints()[0]:
3163 244 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
3164 244 storres
                               str(lb) + ". Aborting!"
3165 244 storres
            raise Exception(exceptionErrorMess)
3166 244 storres
        #### Set upper bound.
3167 244 storres
        if ub > intvl.endpoints()[1]:
3168 244 storres
            ub = intvl.endpoints()[1]
3169 244 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
3170 244 storres
            "log2(numbers)."
3171 244 storres
            taylCondFailedCount += 1
3172 244 storres
        #### Is interval not degenerate?
3173 244 storres
        if lb >= ub:
3174 244 storres
            exceptionErrorMess = "Degenerate interval: " + \
3175 244 storres
                                "lowerBound(" + str(lb) +\
3176 244 storres
                                ")>= upperBound(" + str(ub) + \
3177 244 storres
                                "). Aborting!"
3178 244 storres
            raise Exception(exceptionErrorMess)
3179 244 storres
        #### Is interval center ok?
3180 244 storres
        if ic <= lb or ic >= ub:
3181 244 storres
            exceptionErrorMess =  "Invalid interval center for " + \
3182 244 storres
                                str(lb) + ',' + str(ic) + ',' +  \
3183 244 storres
                                str(ub) + ". Aborting!"
3184 244 storres
            raise Exception(exceptionErrorMess)
3185 244 storres
        ##### Current interval width and reset future interval width.
3186 244 storres
        bw = ub - lb
3187 244 storres
        nbw = 0
3188 244 storres
        icAsInt = int(ic * toIntegerFactor)
3189 244 storres
        #### The following ratio is always >= 1. In case we may want to
3190 244 storres
        #    enlarge the interval
3191 244 storres
        curTaylErrRat = polyApproxAccur / terr
3192 244 storres
        ### Make the  integral transformations.
3193 244 storres
        #### Bounds and interval center.
3194 244 storres
        intIc = int(ic * toIntegerFactor)
3195 244 storres
        intLb = int(lb * toIntegerFactor) - intIc
3196 244 storres
        intUb = int(ub * toIntegerFactor) - intIc
3197 244 storres
        #
3198 244 storres
        #### Polynomials
3199 244 storres
        basisConstructionTime         = cputime()
3200 244 storres
        ##### To a polynomial with rational coefficients with rational arguments
3201 244 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
3202 244 storres
        ##### To a polynomial with rational coefficients with integer arguments
3203 244 storres
        ratIntP = \
3204 244 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
3205 244 storres
        #####  Ultimately a multivariate polynomial with integer coefficients
3206 244 storres
        #      with integer arguments.
3207 244 storres
        coppersmithTuple = \
3208 244 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
3209 244 storres
                                                        precision,
3210 244 storres
                                                        targetHardnessToRound,
3211 244 storres
                                                        i, t)
3212 244 storres
        #### Recover Coppersmith information.
3213 244 storres
        intIntP = coppersmithTuple[0]
3214 244 storres
        N = coppersmithTuple[1]
3215 244 storres
        nAtAlpha = N^alpha
3216 244 storres
        tBound = coppersmithTuple[2]
3217 244 storres
        leastCommonMultiple = coppersmithTuple[3]
3218 244 storres
        iBound = max(abs(intLb),abs(intUb))
3219 244 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
3220 244 storres
        basisConstructionsCount           += 1
3221 244 storres
        #### Compute the matrix to reduce for debug purpose. Otherwise
3222 244 storres
        #    slz_compute_coppersmith_reduced_polynomials does the job
3223 244 storres
        #    invisibly.
3224 244 storres
        if debug:
3225 244 storres
            matrixToReduce = slz_compute_initial_lattice_matrix(intIntP,
3226 244 storres
                                                                alpha,
3227 244 storres
                                                                N,
3228 244 storres
                                                                iBound,
3229 244 storres
                                                                tBound)
3230 244 storres
            maxNorm     = 0
3231 244 storres
            latticeSize = 0
3232 244 storres
            matrixFile = file('/tmp/matrixToReduce.txt', 'w')
3233 244 storres
            for row in matrixToReduce.rows():
3234 244 storres
                currentNorm = row.norm()
3235 244 storres
                if currentNorm > maxNorm:
3236 244 storres
                    maxNorm = currentNorm
3237 244 storres
                latticeSize += 1
3238 244 storres
                for elem in row:
3239 244 storres
                    matrixFile.write(elem.str(base=2) + ",")
3240 244 storres
                matrixFile.write("\n")
3241 244 storres
            #matrixFile.write(matrixToReduce.str(radix="2") + "\n")
3242 244 storres
            matrixFile.close()
3243 244 storres
            #### We use here binary length as defined in LLL princepts.
3244 244 storres
            binaryLength = latticeSize * log(maxNorm)
3245 244 storres
            print "Binary length:", binaryLength.n()
3246 244 storres
            raise Exception("Deliberate stop here.")
3247 244 storres
        # End if debug
3248 244 storres
        reductionTime                     = cputime()
3249 244 storres
        #### Compute the reduced polynomials.
3250 244 storres
        print "Starting reduction..."
3251 244 storres
        ccReducedPolynomialsList =  \
3252 244 storres
                slz_compute_coppersmith_reduced_polynomials_gram(intIntP,
3253 244 storres
                                                                 alpha,
3254 244 storres
                                                                 N,
3255 244 storres
                                                                 iBound,
3256 244 storres
                                                                 tBound)
3257 244 storres
        print "...reduction accomplished in", cputime(reductionTime), "s."
3258 244 storres
        if ccReducedPolynomialsList is None:
3259 244 storres
            raise Exception("Reduction failed.")
3260 244 storres
        reductionsFullTime    += cputime(reductionTime)
3261 244 storres
        reductionsCount       += 1
3262 244 storres
        if len(ccReducedPolynomialsList) < 2:
3263 244 storres
            print "Nothing to form resultants with."
3264 244 storres
            print
3265 244 storres
            coppCondFailedCount += 1
3266 244 storres
            coppCondFailed = True
3267 244 storres
            ##### Apply a different shrink factor according to
3268 244 storres
            #  the number of compliant polynomials.
3269 244 storres
            if len(ccReducedPolynomialsList) == 0:
3270 244 storres
                ub = lb + bw * noCoppersmithIntervalShrink
3271 244 storres
            else: # At least one compliant polynomial.
3272 244 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
3273 244 storres
            if ub > sdub:
3274 244 storres
                ub = sdub
3275 244 storres
            if lb == ub:
3276 244 storres
                raise Exception("Cant shrink interval \
3277 244 storres
                anymore to get Coppersmith condition.")
3278 244 storres
            nbw = 0
3279 244 storres
            continue
3280 244 storres
        #### We have at least two polynomials.
3281 244 storres
        #    Let us try to compute resultants.
3282 244 storres
        #    For each resultant computed, go for the solutions.
3283 244 storres
        ##### Build the pairs list.
3284 244 storres
        polyPairsList           = []
3285 244 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
3286 244 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
3287 244 storres
                                         len(ccReducedPolynomialsList)):
3288 244 storres
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
3289 244 storres
                                      ccReducedPolynomialsList[polyInnerIndex]))
3290 244 storres
        #### Actual root search.
3291 244 storres
        iRootsSet           = set()
3292 244 storres
        hasNonNullResultant = False
3293 244 storres
        for polyPair in polyPairsList:
3294 244 storres
            resultantsComputationTime   = cputime()
3295 244 storres
            currentResultantI = \
3296 244 storres
                slz_resultant(polyPair[0],
3297 244 storres
                              polyPair[1],
3298 244 storres
                              t)
3299 244 storres
            resultantsComputationsCount    += 1
3300 244 storres
            resultantsComputationsFullTime +=  \
3301 244 storres
                cputime(resultantsComputationTime)
3302 244 storres
            #### Function slz_resultant returns None both for None and O
3303 244 storres
            #    resultants.
3304 244 storres
            if currentResultantI is None:
3305 244 storres
                print "Nul resultant"
3306 244 storres
                continue # Next polyPair.
3307 244 storres
            ## We deleted the currentResultantI computation.
3308 244 storres
            #### We have a non null resultant. From now on, whatever this
3309 244 storres
            #    root search yields, no extra root search is necessary.
3310 244 storres
            hasNonNullResultant = True
3311 244 storres
            #### A constant resultant leads to no root. Root search is done.
3312 244 storres
            if currentResultantI.degree() < 1:
3313 244 storres
                print "Resultant is constant:", currentResultantI
3314 244 storres
                break # There is no root.
3315 244 storres
            #### Actual iroots computation.
3316 244 storres
            rootsComputationTime        = cputime()
3317 244 storres
            iRootsList = Zi(currentResultantI).roots()
3318 244 storres
            rootsComputationsCount      +=  1
3319 244 storres
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
3320 244 storres
            if len(iRootsList) == 0:
3321 244 storres
                print "No roots in \"i\"."
3322 244 storres
                break # No roots in i.
3323 244 storres
            else:
3324 244 storres
                for iRoot in iRootsList:
3325 244 storres
                    # A root is given as a (value, multiplicity) tuple.
3326 244 storres
                    iRootsSet.add(iRoot[0])
3327 244 storres
        # End loop for polyPair in polyParsList. We only loop again if a
3328 244 storres
        # None or zero resultant is found.
3329 244 storres
        #### Prepare for results for the current interval..
3330 244 storres
        intervalResultsList = []
3331 244 storres
        intervalResultsList.append((lb, ub))
3332 244 storres
        #### Check roots.
3333 244 storres
        rootsResultsList = []
3334 244 storres
        for iRoot in iRootsSet:
3335 244 storres
            specificRootResultsList = []
3336 244 storres
            failingBounds           = []
3337 244 storres
            # Root qualifies for modular equation, test it for hardness to round.
3338 244 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + iRoot) / toIntegerFactor)
3339 244 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
3340 244 storres
            #print scalingFunction
3341 244 storres
            scaledHardToRoundCaseAsFloat = \
3342 244 storres
                scalingFunction(hardToRoundCaseAsFloat)
3343 244 storres
            print "Candidate HTRNc at x =", \
3344 244 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
3345 244 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
3346 244 storres
                           function,
3347 244 storres
                           2^-(targetHardnessToRound),
3348 244 storres
                           RRR):
3349 244 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
3350 244 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
3351 244 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
3352 244 storres
                    print "Found in interval."
3353 244 storres
                else:
3354 244 storres
                    print "Found out of interval."
3355 244 storres
                # Check the i root is within the i bound.
3356 244 storres
                if abs(iRoot) > iBound:
3357 244 storres
                    print "IRoot", iRoot, "is out of bounds for modular equation."
3358 244 storres
                    print "i bound:", iBound
3359 244 storres
                    failingBounds.append('i')
3360 244 storres
                    failingBounds.append(iRoot)
3361 244 storres
                    failingBounds.append(iBound)
3362 244 storres
                if len(failingBounds) > 0:
3363 244 storres
                    specificRootResultsList.append(failingBounds)
3364 244 storres
            else: # From slz_is_htrn...
3365 244 storres
                print "is not an HTRN case."
3366 244 storres
            if len(specificRootResultsList) > 0:
3367 244 storres
                rootsResultsList.append(specificRootResultsList)
3368 244 storres
        if len(rootsResultsList) > 0:
3369 244 storres
            intervalResultsList.append(rootsResultsList)
3370 244 storres
        ### Check if a non null resultant was found. If not shrink the interval.
3371 244 storres
        if not hasNonNullResultant:
3372 244 storres
            print "Only null resultants for this reduction, shrinking interval."
3373 244 storres
            resultCondFailed      =  True
3374 244 storres
            resultCondFailedCount += 1
3375 244 storres
            ### Shrink interval for next iteration.
3376 244 storres
            ub = lb + bw * onlyNullResultantsShrink
3377 244 storres
            if ub > sdub:
3378 244 storres
                ub = sdub
3379 244 storres
            nbw = 0
3380 244 storres
            continue
3381 244 storres
        #### An intervalResultsList has at least the bounds.
3382 244 storres
        globalResultsList.append(intervalResultsList)
3383 244 storres
        #### Compute an incremented width for next upper bound, only
3384 244 storres
        #    if not Coppersmith condition nor resultant condition
3385 244 storres
        #    failed at the previous run.
3386 244 storres
        if not coppCondFailed and not resultCondFailed:
3387 244 storres
            nbw = noErrorIntervalStretch * bw
3388 244 storres
        else:
3389 244 storres
            nbw = bw
3390 244 storres
        ##### Reset the failure flags. They will be raised
3391 244 storres
        #     again if needed.
3392 244 storres
        coppCondFailed   = False
3393 244 storres
        resultCondFailed = False
3394 244 storres
        #### For next iteration (at end of loop)
3395 244 storres
        #print "nbw:", nbw
3396 244 storres
        lb  = ub
3397 244 storres
        ub += nbw
3398 244 storres
        if ub > sdub:
3399 244 storres
            ub = sdub
3400 244 storres
        print
3401 244 storres
    # End while True
3402 244 storres
    ## Main loop just ended.
3403 244 storres
    globalWallTime = walltime(wallTimeStart)
3404 244 storres
    globalCpuTime  = cputime(cpuTimeStart)
3405 244 storres
    ## Output results
3406 244 storres
    print ; print "Intervals and HTRNs" ; print
3407 244 storres
    for intervalResultsList in globalResultsList:
3408 244 storres
        intervalResultString = "[" + str(intervalResultsList[0][0]) +\
3409 244 storres
                               "," + str(intervalResultsList[0][1])  + "]"
3410 244 storres
        print intervalResultString,
3411 244 storres
        if len(intervalResultsList) > 1:
3412 244 storres
            rootsResultsList = intervalResultsList[1]
3413 244 storres
            specificRootResultIndex = 0
3414 244 storres
            for specificRootResultsList in rootsResultsList:
3415 244 storres
                if specificRootResultIndex == 0:
3416 244 storres
                    print "\t", specificRootResultsList[0],
3417 244 storres
                else:
3418 244 storres
                    print " " * len(intervalResultString), "\t", \
3419 244 storres
                          specificRootResultsList[0],
3420 244 storres
                if len(specificRootResultsList) > 1:
3421 244 storres
                    print specificRootResultsList[1]
3422 244 storres
                specificRootResultIndex += 1
3423 244 storres
        print ; print
3424 244 storres
    #print globalResultsList
3425 244 storres
    #
3426 244 storres
    print "Timers and counters"
3427 244 storres
    print
3428 244 storres
    print "Number of iterations:", iterCount
3429 244 storres
    print "Taylor condition failures:", taylCondFailedCount
3430 244 storres
    print "Coppersmith condition failures:", coppCondFailedCount
3431 244 storres
    print "Resultant condition failures:", resultCondFailedCount
3432 244 storres
    print "Iterations count: ", iterCount
3433 244 storres
    print "Number of intervals:", len(globalResultsList)
3434 244 storres
    print "Number of basis constructions:", basisConstructionsCount
3435 244 storres
    print "Total CPU time spent in basis constructions:", \
3436 244 storres
        basisConstructionsFullTime
3437 244 storres
    if basisConstructionsCount != 0:
3438 244 storres
        print "Average basis construction CPU time:", \
3439 244 storres
            basisConstructionsFullTime/basisConstructionsCount
3440 244 storres
    print "Number of reductions:", reductionsCount
3441 244 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
3442 244 storres
    if reductionsCount != 0:
3443 244 storres
        print "Average reduction CPU time:", \
3444 244 storres
            reductionsFullTime/reductionsCount
3445 244 storres
    print "Number of resultants computation rounds:", \
3446 244 storres
        resultantsComputationsCount
3447 244 storres
    print "Total CPU time spent in resultants computation rounds:", \
3448 244 storres
        resultantsComputationsFullTime
3449 244 storres
    if resultantsComputationsCount != 0:
3450 244 storres
        print "Average resultants computation round CPU time:", \
3451 244 storres
            resultantsComputationsFullTime/resultantsComputationsCount
3452 244 storres
    print "Number of root finding rounds:", rootsComputationsCount
3453 244 storres
    print "Total CPU time spent in roots finding rounds:", \
3454 244 storres
        rootsComputationsFullTime
3455 244 storres
    if rootsComputationsCount != 0:
3456 244 storres
        print "Average roots finding round CPU time:", \
3457 244 storres
            rootsComputationsFullTime/rootsComputationsCount
3458 244 storres
    print "Global Wall time:", globalWallTime
3459 244 storres
    print "Global CPU time:", globalCpuTime
3460 244 storres
    ## Output counters
3461 244 storres
# End srs_runSLZ-v05_gram
3462 244 storres
#
3463 247 storres
def srs_run_SLZ_v05_proj(inputFunction,
3464 247 storres
                         inputLowerBound,
3465 247 storres
                         inputUpperBound,
3466 247 storres
                         alpha,
3467 247 storres
                         degree,
3468 247 storres
                         precision,
3469 247 storres
                         emin,
3470 247 storres
                         emax,
3471 247 storres
                         targetHardnessToRound,
3472 247 storres
                         debug = False):
3473 247 storres
    """
3474 247 storres
    changes from plain V5:
3475 247 storres
       LLL reduction is not performed on the matrix itself but rather on the
3476 247 storres
       product of the matrix with a uniform random matrix.
3477 247 storres
       The reduced matrix obtained is discarded but the transformation matrix
3478 247 storres
       obtained is used to multiply the original matrix in order to reduced it.
3479 247 storres
       If a sufficient level of reduction is obtained, we stop here. If not
3480 247 storres
       the product matrix obtained above is LLL reduced. But as it has been
3481 247 storres
       pre-reduced at the above step, reduction is supposed to be much fastet.
3482 249 storres
       In the worst case, both reductions combined should hopefully be faster
3483 249 storres
       than a straight single reduction.
3484 247 storres
    Changes from V4:
3485 247 storres
        Approximation polynomial has coefficients rounded.
3486 247 storres
    Changes from V3:
3487 247 storres
        Root search is changed again:
3488 247 storres
            - only resultants in i are computed;
3489 247 storres
            - roots in i are searched for;
3490 247 storres
            - if any, they are tested for hardness-to-round.
3491 247 storres
    Changes from V2:
3492 247 storres
        Root search is changed:
3493 247 storres
            - we compute the resultants in i and in t;
3494 247 storres
            - we compute the roots set of each of these resultants;
3495 247 storres
            - we combine all the possible pairs between the two sets;
3496 247 storres
            - we check these pairs in polynomials for correctness.
3497 247 storres
    Changes from V1:
3498 247 storres
        1- check for roots as soon as a resultant is computed;
3499 247 storres
        2- once a non null resultant is found, check for roots;
3500 247 storres
        3- constant resultant == no root.
3501 247 storres
    """
3502 247 storres
3503 247 storres
    if debug:
3504 247 storres
        print "Function                :", inputFunction
3505 247 storres
        print "Lower bound             :", inputLowerBound
3506 247 storres
        print "Upper bounds            :", inputUpperBound
3507 247 storres
        print "Alpha                   :", alpha
3508 247 storres
        print "Degree                  :", degree
3509 247 storres
        print "Precision               :", precision
3510 247 storres
        print "Emin                    :", emin
3511 247 storres
        print "Emax                    :", emax
3512 247 storres
        print "Target hardness-to-round:", targetHardnessToRound
3513 247 storres
        print
3514 247 storres
    ## Important constants.
3515 247 storres
    ### Stretch the interval if no error happens.
3516 247 storres
    noErrorIntervalStretch = 1 + 2^(-5)
3517 247 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
3518 247 storres
    #   by the following factor.
3519 247 storres
    noCoppersmithIntervalShrink = 1/2
3520 247 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
3521 247 storres
    #   shrink the interval by the following factor.
3522 247 storres
    oneCoppersmithIntervalShrink = 3/4
3523 247 storres
    #### If only null resultants are found, shrink the interval by the
3524 247 storres
    #    following factor.
3525 247 storres
    onlyNullResultantsShrink     = 3/4
3526 247 storres
    ## Structures.
3527 247 storres
    RRR         = RealField(precision)
3528 247 storres
    RRIF        = RealIntervalField(precision)
3529 247 storres
    ## Converting input bound into the "right" field.
3530 247 storres
    lowerBound = RRR(inputLowerBound)
3531 247 storres
    upperBound = RRR(inputUpperBound)
3532 247 storres
    ## Before going any further, check domain and image binade conditions.
3533 247 storres
    print inputFunction(1).n()
3534 247 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
3535 247 storres
    if output is None:
3536 247 storres
        print "Invalid domain/image binades. Domain:",\
3537 247 storres
        lowerBound, upperBound, "Images:", \
3538 247 storres
        inputFunction(lowerBound), inputFunction(upperBound)
3539 247 storres
        raise Exception("Invalid domain/image binades.")
3540 247 storres
    lb = output[0] ; ub = output[1]
3541 247 storres
    if lb != lowerBound or ub != upperBound:
3542 247 storres
        print "lb:", lb, " - ub:", ub
3543 247 storres
        print "Invalid domain/image binades. Domain:",\
3544 247 storres
        lowerBound, upperBound, "Images:", \
3545 247 storres
        inputFunction(lowerBound), inputFunction(upperBound)
3546 247 storres
        raise Exception("Invalid domain/image binades.")
3547 247 storres
    #
3548 247 storres
    ## Progam initialization
3549 247 storres
    ### Approximation polynomial accuracy and hardness to round.
3550 247 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
3551 247 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
3552 247 storres
    ### Significand to integer conversion ratio.
3553 247 storres
    toIntegerFactor           = 2^(precision-1)
3554 247 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
3555 247 storres
    ### Variables and rings for polynomials and root searching.
3556 247 storres
    i=var('i')
3557 247 storres
    t=var('t')
3558 247 storres
    inputFunctionVariable = inputFunction.variables()[0]
3559 247 storres
    function = inputFunction.subs({inputFunctionVariable:i})
3560 247 storres
    #  Polynomial Rings over the integers, for root finding.
3561 247 storres
    Zi = ZZ[i]
3562 247 storres
    Zt = ZZ[t]
3563 247 storres
    Zit = ZZ[i,t]
3564 247 storres
    ## Number of iterations limit.
3565 247 storres
    maxIter = 100000
3566 247 storres
    #
3567 247 storres
    ## Set the variable name in Sollya.
3568 247 storres
    pobyso_name_free_variable_sa_so(str(function.variables()[0]))
3569 247 storres
    ## Compute the scaled function and the degree, in their Sollya version
3570 247 storres
    #  once for all.
3571 247 storres
    (scaledf, sdlb, sdub, silb, siub) = \
3572 247 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
3573 247 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
3574 247 storres
    #print "Scaled bounds:", sdlb, sdub
3575 247 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
3576 247 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
3577 247 storres
    #
3578 247 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
3579 247 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
3580 247 storres
    (unscalingFunction, scalingFunction) = \
3581 247 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
3582 247 storres
    #print scalingFunction, unscalingFunction
3583 247 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
3584 247 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
3585 247 storres
    if internalSollyaPrec < 192:
3586 247 storres
        internalSollyaPrec = 192
3587 247 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
3588 247 storres
    print "Sollya internal precision:", internalSollyaPrec
3589 247 storres
    ## Some variables.
3590 247 storres
    ### General variables
3591 247 storres
    lb                  = sdlb
3592 247 storres
    ub                  = sdub
3593 247 storres
    nbw                 = 0
3594 247 storres
    intervalUlp         = ub.ulp()
3595 247 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
3596 247 storres
    ic                  = 0
3597 247 storres
    icAsInt             = 0    # Set from ic.
3598 247 storres
    solutionsSet        = set()
3599 247 storres
    tsErrorWidth        = []
3600 247 storres
    csErrorVectors      = []
3601 247 storres
    csVectorsResultants = []
3602 247 storres
    floatP              = 0  # Taylor polynomial.
3603 247 storres
    floatPcv            = 0  # Ditto with variable change.
3604 247 storres
    intvl               = "" # Taylor interval
3605 247 storres
    terr                = 0  # Taylor error.
3606 247 storres
    iterCount = 0
3607 247 storres
    htrnSet = set()
3608 247 storres
    ### Timers and counters.
3609 247 storres
    wallTimeStart                   = 0
3610 247 storres
    cpuTimeStart                    = 0
3611 247 storres
    taylCondFailedCount             = 0
3612 247 storres
    coppCondFailedCount             = 0
3613 247 storres
    resultCondFailedCount           = 0
3614 247 storres
    coppCondFailed                  = False
3615 247 storres
    resultCondFailed                = False
3616 247 storres
    globalResultsList               = []
3617 247 storres
    basisConstructionsCount         = 0
3618 247 storres
    basisConstructionsFullTime      = 0
3619 247 storres
    basisConstructionTime           = 0
3620 247 storres
    reductionsCount                 = 0
3621 247 storres
    reductionsFullTime              = 0
3622 247 storres
    reductionTime                   = 0
3623 247 storres
    resultantsComputationsCount     = 0
3624 247 storres
    resultantsComputationsFullTime  = 0
3625 247 storres
    resultantsComputationTime       = 0
3626 247 storres
    rootsComputationsCount          = 0
3627 247 storres
    rootsComputationsFullTime       = 0
3628 247 storres
    rootsComputationTime            = 0
3629 247 storres
    print
3630 247 storres
    ## Global times are started here.
3631 247 storres
    wallTimeStart                   = walltime()
3632 247 storres
    cpuTimeStart                    = cputime()
3633 247 storres
    ## Main loop.
3634 247 storres
    while True:
3635 247 storres
        if lb >= sdub:
3636 247 storres
            print "Lower bound reached upper bound."
3637 247 storres
            break
3638 247 storres
        if iterCount == maxIter:
3639 247 storres
            print "Reached maxIter. Aborting"
3640 247 storres
            break
3641 247 storres
        iterCount += 1
3642 247 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
3643 247 storres
            "log2(numbers)."
3644 247 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
3645 247 storres
        prceSo = slz_compute_polynomial_and_interval_01(scaledfSo,
3646 247 storres
                                                        degreeSo,
3647 247 storres
                                                        lb,
3648 247 storres
                                                        ub,
3649 247 storres
                                                        polyApproxAccur)
3650 247 storres
        if debug:
3651 247 storres
            print "Approximation polynomial computed."
3652 247 storres
        if prceSo is None:
3653 247 storres
            raise Exception("Could not compute an approximation polynomial.")
3654 247 storres
        ### Convert back the data into Sage space.
3655 247 storres
        (floatP, floatPcv, intvl, ic, terr) = \
3656 247 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
3657 247 storres
                                                 prceSo[1], prceSo[2],
3658 247 storres
                                                 prceSo[3]))
3659 247 storres
        intvl = RRIF(intvl)
3660 247 storres
        ## Clean-up Sollya stuff.
3661 247 storres
        for elem in prceSo:
3662 247 storres
            sollya_lib_clear_obj(elem)
3663 247 storres
        #print  floatP, floatPcv, intvl, ic, terr
3664 247 storres
        #print floatP
3665 247 storres
        #print intvl.endpoints()[0].n(), \
3666 247 storres
        #      ic.n(),
3667 247 storres
        #intvl.endpoints()[1].n()
3668 247 storres
        ### Check returned data.
3669 247 storres
        #### Is approximation error OK?
3670 247 storres
        if terr > polyApproxAccur:
3671 247 storres
            exceptionErrorMess  = \
3672 247 storres
                "Approximation failed - computed error:" + \
3673 247 storres
                str(terr) + " - target error: "
3674 247 storres
            exceptionErrorMess += \
3675 247 storres
                str(polyApproxAccur) + ". Aborting!"
3676 247 storres
            raise Exception(exceptionErrorMess)
3677 247 storres
        #### Is lower bound OK?
3678 247 storres
        if lb != intvl.endpoints()[0]:
3679 247 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
3680 247 storres
                               str(lb) + ". Aborting!"
3681 247 storres
            raise Exception(exceptionErrorMess)
3682 247 storres
        #### Set upper bound.
3683 247 storres
        if ub > intvl.endpoints()[1]:
3684 247 storres
            ub = intvl.endpoints()[1]
3685 247 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
3686 247 storres
            "log2(numbers)."
3687 247 storres
            taylCondFailedCount += 1
3688 247 storres
        #### Is interval not degenerate?
3689 247 storres
        if lb >= ub:
3690 247 storres
            exceptionErrorMess = "Degenerate interval: " + \
3691 247 storres
                                "lowerBound(" + str(lb) +\
3692 247 storres
                                ")>= upperBound(" + str(ub) + \
3693 247 storres
                                "). Aborting!"
3694 247 storres
            raise Exception(exceptionErrorMess)
3695 247 storres
        #### Is interval center ok?
3696 247 storres
        if ic <= lb or ic >= ub:
3697 247 storres
            exceptionErrorMess =  "Invalid interval center for " + \
3698 247 storres
                                str(lb) + ',' + str(ic) + ',' +  \
3699 247 storres
                                str(ub) + ". Aborting!"
3700 247 storres
            raise Exception(exceptionErrorMess)
3701 247 storres
        ##### Current interval width and reset future interval width.
3702 247 storres
        bw = ub - lb
3703 247 storres
        nbw = 0
3704 247 storres
        icAsInt = int(ic * toIntegerFactor)
3705 247 storres
        #### The following ratio is always >= 1. In case we may want to
3706 247 storres
        #    enlarge the interval
3707 247 storres
        curTaylErrRat = polyApproxAccur / terr
3708 247 storres
        ### Make the  integral transformations.
3709 247 storres
        #### Bounds and interval center.
3710 247 storres
        intIc = int(ic * toIntegerFactor)
3711 247 storres
        intLb = int(lb * toIntegerFactor) - intIc
3712 247 storres
        intUb = int(ub * toIntegerFactor) - intIc
3713 247 storres
        #
3714 247 storres
        #### Polynomials
3715 247 storres
        basisConstructionTime         = cputime()
3716 247 storres
        ##### To a polynomial with rational coefficients with rational arguments
3717 247 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
3718 247 storres
        ##### To a polynomial with rational coefficients with integer arguments
3719 247 storres
        ratIntP = \
3720 247 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
3721 247 storres
        #####  Ultimately a multivariate polynomial with integer coefficients
3722 247 storres
        #      with integer arguments.
3723 247 storres
        coppersmithTuple = \
3724 247 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
3725 247 storres
                                                        precision,
3726 247 storres
                                                        targetHardnessToRound,
3727 247 storres
                                                        i, t)
3728 247 storres
        #### Recover Coppersmith information.
3729 247 storres
        intIntP = coppersmithTuple[0]
3730 247 storres
        N = coppersmithTuple[1]
3731 247 storres
        nAtAlpha = N^alpha
3732 247 storres
        tBound = coppersmithTuple[2]
3733 247 storres
        leastCommonMultiple = coppersmithTuple[3]
3734 247 storres
        iBound = max(abs(intLb),abs(intUb))
3735 247 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
3736 247 storres
        basisConstructionsCount           += 1
3737 247 storres
        #### Compute the matrix to reduce for debug purpose. Otherwise
3738 247 storres
        #    slz_compute_coppersmith_reduced_polynomials does the job
3739 247 storres
        #    invisibly.
3740 247 storres
        if debug:
3741 247 storres
            matrixToReduce = slz_compute_initial_lattice_matrix(intIntP,
3742 247 storres
                                                                alpha,
3743 247 storres
                                                                N,
3744 247 storres
                                                                iBound,
3745 247 storres
                                                                tBound)
3746 247 storres
            maxNorm     = 0
3747 247 storres
            latticeSize = 0
3748 247 storres
            matrixFile = file('/tmp/matrixToReduce.txt', 'w')
3749 247 storres
            for row in matrixToReduce.rows():
3750 247 storres
                currentNorm = row.norm()
3751 247 storres
                if currentNorm > maxNorm:
3752 247 storres
                    maxNorm = currentNorm
3753 247 storres
                latticeSize += 1
3754 247 storres
                for elem in row:
3755 247 storres
                    matrixFile.write(elem.str(base=2) + ",")
3756 247 storres
                matrixFile.write("\n")
3757 247 storres
            #matrixFile.write(matrixToReduce.str(radix="2") + "\n")
3758 247 storres
            matrixFile.close()
3759 247 storres
            #### We use here binary length as defined in LLL princepts.
3760 247 storres
            binaryLength = latticeSize * log(maxNorm)
3761 247 storres
            print "Binary length:", binaryLength.n()
3762 249 storres
            #raise Exception("Deliberate stop here.")
3763 247 storres
        # End if debug
3764 247 storres
        reductionTime                     = cputime()
3765 247 storres
        #### Compute the reduced polynomials.
3766 247 storres
        print "Starting reduction..."
3767 247 storres
        ccReducedPolynomialsList =  \
3768 247 storres
                slz_compute_coppersmith_reduced_polynomials_proj(intIntP,
3769 247 storres
                                                                 alpha,
3770 247 storres
                                                                 N,
3771 247 storres
                                                                 iBound,
3772 247 storres
                                                                 tBound)
3773 247 storres
        print "...reduction accomplished in", cputime(reductionTime), "s."
3774 247 storres
        if ccReducedPolynomialsList is None:
3775 247 storres
            raise Exception("Reduction failed.")
3776 247 storres
        reductionsFullTime    += cputime(reductionTime)
3777 247 storres
        reductionsCount       += 1
3778 247 storres
        if len(ccReducedPolynomialsList) < 2:
3779 247 storres
            print "Nothing to form resultants with."
3780 247 storres
            print
3781 247 storres
            coppCondFailedCount += 1
3782 247 storres
            coppCondFailed = True
3783 247 storres
            ##### Apply a different shrink factor according to
3784 247 storres
            #  the number of compliant polynomials.
3785 247 storres
            if len(ccReducedPolynomialsList) == 0:
3786 247 storres
                ub = lb + bw * noCoppersmithIntervalShrink
3787 247 storres
            else: # At least one compliant polynomial.
3788 247 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
3789 247 storres
            if ub > sdub:
3790 247 storres
                ub = sdub
3791 247 storres
            if lb == ub:
3792 247 storres
                raise Exception("Cant shrink interval \
3793 247 storres
                anymore to get Coppersmith condition.")
3794 247 storres
            nbw = 0
3795 247 storres
            continue
3796 247 storres
        #### We have at least two polynomials.
3797 247 storres
        #    Let us try to compute resultants.
3798 247 storres
        #    For each resultant computed, go for the solutions.
3799 247 storres
        ##### Build the pairs list.
3800 247 storres
        polyPairsList           = []
3801 247 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
3802 247 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
3803 247 storres
                                         len(ccReducedPolynomialsList)):
3804 247 storres
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
3805 247 storres
                                      ccReducedPolynomialsList[polyInnerIndex]))
3806 247 storres
        #### Actual root search.
3807 247 storres
        iRootsSet           = set()
3808 247 storres
        hasNonNullResultant = False
3809 247 storres
        for polyPair in polyPairsList:
3810 247 storres
            resultantsComputationTime   = cputime()
3811 247 storres
            currentResultantI = \
3812 247 storres
                slz_resultant(polyPair[0],
3813 247 storres
                              polyPair[1],
3814 247 storres
                              t)
3815 247 storres
            resultantsComputationsCount    += 1
3816 247 storres
            resultantsComputationsFullTime +=  \
3817 247 storres
                cputime(resultantsComputationTime)
3818 247 storres
            #### Function slz_resultant returns None both for None and O
3819 247 storres
            #    resultants.
3820 247 storres
            if currentResultantI is None:
3821 247 storres
                print "Nul resultant"
3822 247 storres
                continue # Next polyPair.
3823 247 storres
            ## We deleted the currentResultantI computation.
3824 247 storres
            #### We have a non null resultant. From now on, whatever this
3825 247 storres
            #    root search yields, no extra root search is necessary.
3826 247 storres
            hasNonNullResultant = True
3827 247 storres
            #### A constant resultant leads to no root. Root search is done.
3828 247 storres
            if currentResultantI.degree() < 1:
3829 247 storres
                print "Resultant is constant:", currentResultantI
3830 247 storres
                break # There is no root.
3831 247 storres
            #### Actual iroots computation.
3832 247 storres
            rootsComputationTime        = cputime()
3833 247 storres
            iRootsList = Zi(currentResultantI).roots()
3834 247 storres
            rootsComputationsCount      +=  1
3835 247 storres
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
3836 247 storres
            if len(iRootsList) == 0:
3837 247 storres
                print "No roots in \"i\"."
3838 247 storres
                break # No roots in i.
3839 247 storres
            else:
3840 247 storres
                for iRoot in iRootsList:
3841 247 storres
                    # A root is given as a (value, multiplicity) tuple.
3842 247 storres
                    iRootsSet.add(iRoot[0])
3843 247 storres
        # End loop for polyPair in polyParsList. We only loop again if a
3844 247 storres
        # None or zero resultant is found.
3845 247 storres
        #### Prepare for results for the current interval..
3846 247 storres
        intervalResultsList = []
3847 247 storres
        intervalResultsList.append((lb, ub))
3848 247 storres
        #### Check roots.
3849 247 storres
        rootsResultsList = []
3850 247 storres
        for iRoot in iRootsSet:
3851 247 storres
            specificRootResultsList = []
3852 247 storres
            failingBounds           = []
3853 247 storres
            # Root qualifies for modular equation, test it for hardness to round.
3854 247 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + iRoot) / toIntegerFactor)
3855 247 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
3856 247 storres
            #print scalingFunction
3857 247 storres
            scaledHardToRoundCaseAsFloat = \
3858 247 storres
                scalingFunction(hardToRoundCaseAsFloat)
3859 247 storres
            print "Candidate HTRNc at x =", \
3860 247 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
3861 247 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
3862 247 storres
                           function,
3863 247 storres
                           2^-(targetHardnessToRound),
3864 247 storres
                           RRR):
3865 247 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
3866 247 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
3867 247 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
3868 247 storres
                    print "Found in interval."
3869 247 storres
                else:
3870 247 storres
                    print "Found out of interval."
3871 247 storres
                # Check the i root is within the i bound.
3872 247 storres
                if abs(iRoot) > iBound:
3873 247 storres
                    print "IRoot", iRoot, "is out of bounds for modular equation."
3874 247 storres
                    print "i bound:", iBound
3875 247 storres
                    failingBounds.append('i')
3876 247 storres
                    failingBounds.append(iRoot)
3877 247 storres
                    failingBounds.append(iBound)
3878 247 storres
                if len(failingBounds) > 0:
3879 247 storres
                    specificRootResultsList.append(failingBounds)
3880 247 storres
            else: # From slz_is_htrn...
3881 247 storres
                print "is not an HTRN case."
3882 247 storres
            if len(specificRootResultsList) > 0:
3883 247 storres
                rootsResultsList.append(specificRootResultsList)
3884 247 storres
        if len(rootsResultsList) > 0:
3885 247 storres
            intervalResultsList.append(rootsResultsList)
3886 247 storres
        ### Check if a non null resultant was found. If not shrink the interval.
3887 247 storres
        if not hasNonNullResultant:
3888 247 storres
            print "Only null resultants for this reduction, shrinking interval."
3889 247 storres
            resultCondFailed      =  True
3890 247 storres
            resultCondFailedCount += 1
3891 247 storres
            ### Shrink interval for next iteration.
3892 247 storres
            ub = lb + bw * onlyNullResultantsShrink
3893 247 storres
            if ub > sdub:
3894 247 storres
                ub = sdub
3895 247 storres
            nbw = 0
3896 247 storres
            continue
3897 247 storres
        #### An intervalResultsList has at least the bounds.
3898 247 storres
        globalResultsList.append(intervalResultsList)
3899 247 storres
        #### Compute an incremented width for next upper bound, only
3900 247 storres
        #    if not Coppersmith condition nor resultant condition
3901 247 storres
        #    failed at the previous run.
3902 247 storres
        if not coppCondFailed and not resultCondFailed:
3903 247 storres
            nbw = noErrorIntervalStretch * bw
3904 247 storres
        else:
3905 247 storres
            nbw = bw
3906 247 storres
        ##### Reset the failure flags. They will be raised
3907 247 storres
        #     again if needed.
3908 247 storres
        coppCondFailed   = False
3909 247 storres
        resultCondFailed = False
3910 247 storres
        #### For next iteration (at end of loop)
3911 247 storres
        #print "nbw:", nbw
3912 247 storres
        lb  = ub
3913 247 storres
        ub += nbw
3914 247 storres
        if ub > sdub:
3915 247 storres
            ub = sdub
3916 247 storres
        print
3917 247 storres
    # End while True
3918 247 storres
    ## Main loop just ended.
3919 247 storres
    globalWallTime = walltime(wallTimeStart)
3920 247 storres
    globalCpuTime  = cputime(cpuTimeStart)
3921 247 storres
    ## Output results
3922 247 storres
    print ; print "Intervals and HTRNs" ; print
3923 247 storres
    for intervalResultsList in globalResultsList:
3924 247 storres
        intervalResultString = "[" + str(intervalResultsList[0][0]) +\
3925 247 storres
                               "," + str(intervalResultsList[0][1])  + "]"
3926 247 storres
        print intervalResultString,
3927 247 storres
        if len(intervalResultsList) > 1:
3928 247 storres
            rootsResultsList = intervalResultsList[1]
3929 247 storres
            specificRootResultIndex = 0
3930 247 storres
            for specificRootResultsList in rootsResultsList:
3931 247 storres
                if specificRootResultIndex == 0:
3932 247 storres
                    print "\t", specificRootResultsList[0],
3933 247 storres
                else:
3934 247 storres
                    print " " * len(intervalResultString), "\t", \
3935 247 storres
                          specificRootResultsList[0],
3936 247 storres
                if len(specificRootResultsList) > 1:
3937 247 storres
                    print specificRootResultsList[1]
3938 247 storres
                specificRootResultIndex += 1
3939 247 storres
        print ; print
3940 247 storres
    #print globalResultsList
3941 247 storres
    #
3942 247 storres
    print "Timers and counters"
3943 247 storres
    print
3944 247 storres
    print "Number of iterations:", iterCount
3945 247 storres
    print "Taylor condition failures:", taylCondFailedCount
3946 247 storres
    print "Coppersmith condition failures:", coppCondFailedCount
3947 247 storres
    print "Resultant condition failures:", resultCondFailedCount
3948 247 storres
    print "Iterations count: ", iterCount
3949 247 storres
    print "Number of intervals:", len(globalResultsList)
3950 247 storres
    print "Number of basis constructions:", basisConstructionsCount
3951 247 storres
    print "Total CPU time spent in basis constructions:", \
3952 247 storres
        basisConstructionsFullTime
3953 247 storres
    if basisConstructionsCount != 0:
3954 247 storres
        print "Average basis construction CPU time:", \
3955 247 storres
            basisConstructionsFullTime/basisConstructionsCount
3956 247 storres
    print "Number of reductions:", reductionsCount
3957 247 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
3958 247 storres
    if reductionsCount != 0:
3959 247 storres
        print "Average reduction CPU time:", \
3960 247 storres
            reductionsFullTime/reductionsCount
3961 247 storres
    print "Number of resultants computation rounds:", \
3962 247 storres
        resultantsComputationsCount
3963 247 storres
    print "Total CPU time spent in resultants computation rounds:", \
3964 247 storres
        resultantsComputationsFullTime
3965 247 storres
    if resultantsComputationsCount != 0:
3966 247 storres
        print "Average resultants computation round CPU time:", \
3967 247 storres
            resultantsComputationsFullTime/resultantsComputationsCount
3968 247 storres
    print "Number of root finding rounds:", rootsComputationsCount
3969 247 storres
    print "Total CPU time spent in roots finding rounds:", \
3970 247 storres
        rootsComputationsFullTime
3971 247 storres
    if rootsComputationsCount != 0:
3972 247 storres
        print "Average roots finding round CPU time:", \
3973 247 storres
            rootsComputationsFullTime/rootsComputationsCount
3974 247 storres
    print "Global Wall time:", globalWallTime
3975 247 storres
    print "Global CPU time:", globalCpuTime
3976 247 storres
    ## Output counters
3977 247 storres
# End srs_runSLZ-v05_proj
3978 247 storres
#
3979 222 storres
def srs_run_SLZ_v06(inputFunction,
3980 222 storres
                    inputLowerBound,
3981 222 storres
                    inputUpperBound,
3982 222 storres
                    alpha,
3983 222 storres
                    degree,
3984 222 storres
                    precision,
3985 222 storres
                    emin,
3986 222 storres
                    emax,
3987 222 storres
                    targetHardnessToRound,
3988 222 storres
                    debug = True):
3989 222 storres
    """
3990 222 storres
    Changes from V5:
3991 222 storres
        Very verbose
3992 222 storres
    Changes from V4:
3993 222 storres
        Approximation polynomial has coefficients rounded.
3994 222 storres
    Changes from V3:
3995 222 storres
        Root search is changed again:
3996 222 storres
            - only resultants in i are computed;
3997 222 storres
            - roots in i are searched for;
3998 222 storres
            - if any, they are tested for hardness-to-round.
3999 222 storres
    Changes from V2:
4000 222 storres
        Root search is changed:
4001 222 storres
            - we compute the resultants in i and in t;
4002 222 storres
            - we compute the roots set of each of these resultants;
4003 222 storres
            - we combine all the possible pairs between the two sets;
4004 222 storres
            - we check these pairs in polynomials for correctness.
4005 222 storres
    Changes from V1:
4006 222 storres
        1- check for roots as soon as a resultant is computed;
4007 222 storres
        2- once a non null resultant is found, check for roots;
4008 222 storres
        3- constant resultant == no root.
4009 222 storres
    """
4010 222 storres
    if debug:
4011 222 storres
        print "Function                :", inputFunction
4012 222 storres
        print "Lower bound             :", inputLowerBound
4013 222 storres
        print "Upper bounds            :", inputUpperBound
4014 222 storres
        print "Alpha                   :", alpha
4015 222 storres
        print "Degree                  :", degree
4016 222 storres
        print "Precision               :", precision
4017 222 storres
        print "Emin                    :", emin
4018 222 storres
        print "Emax                    :", emax
4019 222 storres
        print "Target hardness-to-round:", targetHardnessToRound
4020 222 storres
        print
4021 222 storres
    ## Important constants.
4022 222 storres
    ### Stretch the interval if no error happens.
4023 222 storres
    noErrorIntervalStretch = 1 + 2^(-5)
4024 222 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
4025 222 storres
    #   by the following factor.
4026 222 storres
    noCoppersmithIntervalShrink = 1/2
4027 222 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
4028 222 storres
    #   shrink the interval by the following factor.
4029 222 storres
    oneCoppersmithIntervalShrink = 3/4
4030 222 storres
    #### If only null resultants are found, shrink the interval by the
4031 222 storres
    #    following factor.
4032 222 storres
    onlyNullResultantsShrink     = 3/4
4033 222 storres
    ## Structures.
4034 222 storres
    RRR         = RealField(precision)
4035 222 storres
    RRIF        = RealIntervalField(precision)
4036 222 storres
    ## Converting input bound into the "right" field.
4037 222 storres
    lowerBound = RRR(inputLowerBound)
4038 222 storres
    upperBound = RRR(inputUpperBound)
4039 222 storres
    ## Before going any further, check domain and image binade conditions.
4040 222 storres
    print inputFunction(1).n()
4041 222 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
4042 222 storres
    if output is None:
4043 222 storres
        print "Invalid domain/image binades. Domain:",\
4044 222 storres
        lowerBound, upperBound, "Images:", \
4045 222 storres
        inputFunction(lowerBound), inputFunction(upperBound)
4046 222 storres
        raise Exception("Invalid domain/image binades.")
4047 222 storres
    lb = output[0] ; ub = output[1]
4048 222 storres
    if lb != lowerBound or ub != upperBound:
4049 222 storres
        print "lb:", lb, " - ub:", ub
4050 222 storres
        print "Invalid domain/image binades. Domain:",\
4051 222 storres
        lowerBound, upperBound, "Images:", \
4052 222 storres
        inputFunction(lowerBound), inputFunction(upperBound)
4053 222 storres
        raise Exception("Invalid domain/image binades.")
4054 222 storres
    #
4055 222 storres
    ## Progam initialization
4056 222 storres
    ### Approximation polynomial accuracy and hardness to round.
4057 222 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
4058 222 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
4059 222 storres
    ### Significand to integer conversion ratio.
4060 222 storres
    toIntegerFactor           = 2^(precision-1)
4061 222 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
4062 222 storres
    ### Variables and rings for polynomials and root searching.
4063 222 storres
    i=var('i')
4064 222 storres
    t=var('t')
4065 222 storres
    inputFunctionVariable = inputFunction.variables()[0]
4066 222 storres
    function = inputFunction.subs({inputFunctionVariable:i})
4067 222 storres
    #  Polynomial Rings over the integers, for root finding.
4068 222 storres
    Zi = ZZ[i]
4069 222 storres
    ## Number of iterations limit.
4070 222 storres
    maxIter = 100000
4071 222 storres
    #
4072 231 storres
    ## Set the variable name in Sollya.
4073 231 storres
    pobyso_name_free_variable_sa_so(str(function.variables()[0]))
4074 222 storres
    ## Compute the scaled function and the degree, in their Sollya version
4075 222 storres
    #  once for all.
4076 222 storres
    (scaledf, sdlb, sdub, silb, siub) = \
4077 222 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
4078 222 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
4079 222 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
4080 222 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
4081 222 storres
    #
4082 222 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
4083 222 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
4084 222 storres
    (unscalingFunction, scalingFunction) = \
4085 222 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
4086 222 storres
    #print scalingFunction, unscalingFunction
4087 222 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
4088 222 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
4089 222 storres
    if internalSollyaPrec < 192:
4090 222 storres
        internalSollyaPrec = 192
4091 227 storres
    pobyso_lib_init()
4092 222 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
4093 222 storres
    print "Sollya internal precision:", internalSollyaPrec
4094 222 storres
    targetPlusOnePrecRF       = RealField(RRR.prec()+1)
4095 222 storres
    if internalSollyaPrec < 1024:
4096 222 storres
        quasiExactRF              = RealField(1014)
4097 222 storres
    else:
4098 222 storres
        quasiExactRF              = RealField(internalSollyaPrec)
4099 222 storres
    ## Some variables.
4100 222 storres
    ### General variables
4101 222 storres
    lb                  = sdlb
4102 222 storres
    ub                  = sdub
4103 222 storres
    nbw                 = 0
4104 222 storres
    intervalUlp         = ub.ulp()
4105 222 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
4106 222 storres
    ic                  = 0
4107 222 storres
    icAsInt             = 0    # Set from ic.
4108 222 storres
    solutionsSet        = set()
4109 222 storres
    tsErrorWidth        = []
4110 222 storres
    csErrorVectors      = []
4111 222 storres
    csVectorsResultants = []
4112 222 storres
    floatP              = 0  # Taylor polynomial.
4113 222 storres
    floatPcv            = 0  # Ditto with variable change.
4114 222 storres
    intvl               = "" # Taylor interval
4115 222 storres
    terr                = 0  # Taylor error.
4116 222 storres
    iterCount = 0
4117 222 storres
    htrnSet = set()
4118 222 storres
    ### Timers and counters.
4119 222 storres
    wallTimeStart                   = 0
4120 222 storres
    cpuTimeStart                    = 0
4121 222 storres
    taylCondFailedCount             = 0
4122 222 storres
    coppCondFailedCount             = 0
4123 222 storres
    resultCondFailedCount           = 0
4124 222 storres
    coppCondFailed                  = False
4125 222 storres
    resultCondFailed                = False
4126 222 storres
    globalResultsList               = []
4127 222 storres
    basisConstructionsCount         = 0
4128 222 storres
    basisConstructionsFullTime      = 0
4129 222 storres
    basisConstructionTime           = 0
4130 222 storres
    reductionsCount                 = 0
4131 222 storres
    reductionsFullTime              = 0
4132 222 storres
    reductionTime                   = 0
4133 222 storres
    resultantsComputationsCount     = 0
4134 222 storres
    resultantsComputationsFullTime  = 0
4135 222 storres
    resultantsComputationTime       = 0
4136 222 storres
    rootsComputationsCount          = 0
4137 222 storres
    rootsComputationsFullTime       = 0
4138 222 storres
    rootsComputationTime            = 0
4139 222 storres
    print
4140 222 storres
    ## Global times are started here.
4141 222 storres
    wallTimeStart                   = walltime()
4142 222 storres
    cpuTimeStart                    = cputime()
4143 222 storres
    ## Main loop.
4144 222 storres
    while True:
4145 222 storres
        if lb >= sdub:
4146 222 storres
            print "Lower bound reached upper bound."
4147 222 storres
            break
4148 222 storres
        if iterCount == maxIter:
4149 222 storres
            print "Reached maxIter. Aborting"
4150 222 storres
            break
4151 222 storres
        iterCount += 1
4152 222 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
4153 222 storres
            "log2(numbers)."
4154 227 storres
        #print "Debugging..."
4155 222 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
4156 227 storres
        prceSo = slz_compute_polynomial_and_interval_02(scaledfSo,
4157 222 storres
                                                        degreeSo,
4158 222 storres
                                                        lb,
4159 222 storres
                                                        ub,
4160 222 storres
                                                        polyApproxAccur,
4161 222 storres
                                                        debug=True)
4162 222 storres
        if debug:
4163 227 storres
            print "Sollya Taylor polynomial:", ; pobyso_autoprint(prceSo[0])
4164 227 storres
            print "Sollya interval         :", ; pobyso_autoprint(prceSo[1])
4165 227 storres
            print "Sollya interval center  :", ; pobyso_autoprint(prceSo[2])
4166 227 storres
            print "Sollya Taylor error     :", ; pobyso_autoprint(prceSo[3])
4167 222 storres
4168 222 storres
        ### Convert back the data into Sage space.
4169 222 storres
        (floatP, floatPcv, intvl, ic, terr) = \
4170 222 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
4171 222 storres
                                                 prceSo[1], prceSo[2],
4172 222 storres
                                                 prceSo[3]))
4173 228 storres
        print "Sage Taylor polynomial:", floatP, floatP.parent()
4174 228 storres
        floatPcoeffs = floatP.coefficients()
4175 228 storres
        for coeff in floatPcoeffs:
4176 228 storres
            print coeff.n(prec=coeff.parent().prec()).str(base=2)
4177 228 storres
            print coeff.n(prec=coeff.parent().prec())
4178 222 storres
        intvl = RRIF(intvl)
4179 222 storres
        ## Clean-up Sollya stuff.
4180 222 storres
        for elem in prceSo:
4181 222 storres
            sollya_lib_clear_obj(elem)
4182 222 storres
        #print  floatP, floatPcv, intvl, ic, terr
4183 222 storres
        #print floatP
4184 222 storres
        #print intvl.endpoints()[0].n(), \
4185 222 storres
        #      ic.n(),
4186 222 storres
        #intvl.endpoints()[1].n()
4187 222 storres
        ### Check returned data.
4188 222 storres
        #### Is approximation error OK?
4189 222 storres
        if terr > polyApproxAccur:
4190 222 storres
            exceptionErrorMess  = \
4191 222 storres
                "Approximation failed - computed error:" + \
4192 222 storres
                str(terr) + " - target error: "
4193 222 storres
            exceptionErrorMess += \
4194 222 storres
                str(polyApproxAccur) + ". Aborting!"
4195 222 storres
            raise Exception(exceptionErrorMess)
4196 222 storres
        #### Is lower bound OK?
4197 222 storres
        if lb != intvl.endpoints()[0]:
4198 222 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
4199 222 storres
                               str(lb) + ". Aborting!"
4200 222 storres
            raise Exception(exceptionErrorMess)
4201 222 storres
        #### Set upper bound.
4202 222 storres
        if ub > intvl.endpoints()[1]:
4203 222 storres
            ub = intvl.endpoints()[1]
4204 222 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
4205 222 storres
            "log2(numbers)."
4206 222 storres
            taylCondFailedCount += 1
4207 222 storres
        #### Is interval not degenerate?
4208 222 storres
        if lb >= ub:
4209 222 storres
            exceptionErrorMess = "Degenerate interval: " + \
4210 222 storres
                                "lowerBound(" + str(lb) +\
4211 222 storres
                                ")>= upperBound(" + str(ub) + \
4212 222 storres
                                "). Aborting!"
4213 222 storres
            raise Exception(exceptionErrorMess)
4214 222 storres
        #### Is interval center ok?
4215 222 storres
        if ic <= lb or ic >= ub:
4216 222 storres
            exceptionErrorMess =  "Invalid interval center for " + \
4217 222 storres
                                str(lb) + ',' + str(ic) + ',' +  \
4218 222 storres
                                str(ub) + ". Aborting!"
4219 222 storres
            raise Exception(exceptionErrorMess)
4220 222 storres
        ##### Current interval width and reset future interval width.
4221 222 storres
        bw = ub - lb
4222 222 storres
        nbw = 0
4223 222 storres
        icAsInt = int(ic * toIntegerFactor)
4224 222 storres
        #### The following ratio is always >= 1. In case we may want to
4225 222 storres
        #    enlarge the interval
4226 222 storres
        curTaylErrRat = polyApproxAccur / terr
4227 222 storres
        ### Make the  integral transformations.
4228 222 storres
        #### Bounds and interval center.
4229 222 storres
        intIc = int(ic * toIntegerFactor)
4230 222 storres
        intLb = int(lb * toIntegerFactor) - intIc
4231 222 storres
        intUb = int(ub * toIntegerFactor) - intIc
4232 222 storres
        #
4233 222 storres
        #### Polynomials
4234 222 storres
        basisConstructionTime         = cputime()
4235 222 storres
        ##### To a polynomial with rational coefficients with rational arguments
4236 222 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
4237 222 storres
        if debug:
4238 222 storres
            print "Polynomial: rational coefficients for rational argument:"
4239 222 storres
            print ratRatP
4240 222 storres
        ##### To a polynomial with rational coefficients with integer arguments
4241 222 storres
        ratIntP = \
4242 222 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
4243 222 storres
        if debug:
4244 222 storres
            print "Polynomial: rational coefficients for integer argument:"
4245 222 storres
            print ratIntP
4246 222 storres
        #####  Ultimately a multivariate polynomial with integer coefficients
4247 222 storres
        #      with integer arguments.
4248 222 storres
        coppersmithTuple = \
4249 222 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
4250 222 storres
                                                        precision,
4251 222 storres
                                                        targetHardnessToRound,
4252 222 storres
                                                        i, t)
4253 222 storres
        #### Recover Coppersmith information.
4254 222 storres
        intIntP = coppersmithTuple[0]
4255 222 storres
        N = coppersmithTuple[1]
4256 222 storres
        nAtAlpha = N^alpha
4257 222 storres
        tBound = coppersmithTuple[2]
4258 222 storres
        leastCommonMultiple = coppersmithTuple[3]
4259 222 storres
        iBound = max(abs(intLb),abs(intUb))
4260 222 storres
        if debug:
4261 222 storres
            print "Polynomial: integer coefficients for integer argument:"
4262 222 storres
            print intIntP
4263 222 storres
            print "N:", N
4264 222 storres
            print "t bound:", tBound
4265 222 storres
            print "i bound:", iBound
4266 222 storres
            print "Least common multiple:", leastCommonMultiple
4267 222 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
4268 222 storres
        basisConstructionsCount           += 1
4269 228 storres
4270 222 storres
        #### Compute the matrix to reduce.
4271 222 storres
        matrixToReduce = slz_compute_initial_lattice_matrix(intIntP,
4272 222 storres
                                                            alpha,
4273 222 storres
                                                            N,
4274 222 storres
                                                            iBound,
4275 228 storres
                                                            tBound,
4276 228 storres
                                                            True)
4277 222 storres
        matrixFile = file('/tmp/matrixToReduce.txt', 'w')
4278 222 storres
        for row in matrixToReduce.rows():
4279 222 storres
            matrixFile.write(str(row) + "\n")
4280 222 storres
        matrixFile.close()
4281 228 storres
        #raise Exception("Deliberate stop here.")
4282 228 storres
4283 222 storres
        reductionTime                     = cputime()
4284 222 storres
        #### Compute the reduced polynomials.
4285 222 storres
        ccReducedPolynomialsList =  \
4286 229 storres
                slz_compute_coppersmith_reduced_polynomials_with_lattice_volume(intIntP,
4287 222 storres
                                                            alpha,
4288 222 storres
                                                            N,
4289 222 storres
                                                            iBound,
4290 229 storres
                                                            tBound,
4291 229 storres
                                                            True)
4292 222 storres
        if ccReducedPolynomialsList is None:
4293 222 storres
            raise Exception("Reduction failed.")
4294 222 storres
        reductionsFullTime    += cputime(reductionTime)
4295 222 storres
        reductionsCount       += 1
4296 222 storres
        if len(ccReducedPolynomialsList) < 2:
4297 222 storres
            print "Nothing to form resultants with."
4298 222 storres
            print
4299 222 storres
            coppCondFailedCount += 1
4300 222 storres
            coppCondFailed = True
4301 222 storres
            ##### Apply a different shrink factor according to
4302 222 storres
            #  the number of compliant polynomials.
4303 222 storres
            if len(ccReducedPolynomialsList) == 0:
4304 222 storres
                ub = lb + bw * noCoppersmithIntervalShrink
4305 222 storres
            else: # At least one compliant polynomial.
4306 222 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
4307 222 storres
            if ub > sdub:
4308 222 storres
                ub = sdub
4309 222 storres
            if lb == ub:
4310 222 storres
                raise Exception("Cant shrink interval \
4311 222 storres
                anymore to get Coppersmith condition.")
4312 222 storres
            nbw = 0
4313 222 storres
            continue
4314 222 storres
        #### We have at least two polynomials.
4315 222 storres
        #    Let us try to compute resultants.
4316 222 storres
        #    For each resultant computed, go for the solutions.
4317 222 storres
        ##### Build the pairs list.
4318 222 storres
        polyPairsList           = []
4319 222 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
4320 222 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
4321 222 storres
                                         len(ccReducedPolynomialsList)):
4322 222 storres
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
4323 222 storres
                                      ccReducedPolynomialsList[polyInnerIndex]))
4324 222 storres
        #### Actual root search.
4325 222 storres
        iRootsSet           = set()
4326 222 storres
        hasNonNullResultant = False
4327 222 storres
        for polyPair in polyPairsList:
4328 222 storres
            resultantsComputationTime   = cputime()
4329 222 storres
            currentResultantI = \
4330 222 storres
                slz_resultant(polyPair[0],
4331 222 storres
                              polyPair[1],
4332 229 storres
                              t,
4333 229 storres
                              debug=True)
4334 222 storres
            resultantsComputationsCount    += 1
4335 222 storres
            resultantsComputationsFullTime +=  \
4336 222 storres
                cputime(resultantsComputationTime)
4337 222 storres
            #### Function slz_resultant returns None both for None and O
4338 222 storres
            #    resultants.
4339 222 storres
            if currentResultantI is None:
4340 222 storres
                print "Nul resultant"
4341 222 storres
                continue # Next polyPair.
4342 222 storres
            ## We deleted the currentResultantI computation.
4343 222 storres
            #### We have a non null resultant. From now on, whatever this
4344 222 storres
            #    root search yields, no extra root search is necessary.
4345 222 storres
            hasNonNullResultant = True
4346 222 storres
            #### A constant resultant leads to no root. Root search is done.
4347 222 storres
            if currentResultantI.degree() < 1:
4348 222 storres
                print "Resultant is constant:", currentResultantI
4349 222 storres
                break # There is no root.
4350 222 storres
            #### Actual iroots computation.
4351 222 storres
            rootsComputationTime        = cputime()
4352 222 storres
            iRootsList = Zi(currentResultantI).roots()
4353 222 storres
            rootsComputationsCount      +=  1
4354 222 storres
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
4355 222 storres
            if len(iRootsList) == 0:
4356 222 storres
                print "No roots in \"i\"."
4357 222 storres
                break # No roots in i.
4358 222 storres
            else:
4359 222 storres
                for iRoot in iRootsList:
4360 222 storres
                    # A root is given as a (value, multiplicity) tuple.
4361 222 storres
                    iRootsSet.add(iRoot[0])
4362 222 storres
        # End loop for polyPair in polyParsList. We only loop again if a
4363 222 storres
        # None or zero resultant is found.
4364 222 storres
        #### Prepare for results for the current interval..
4365 222 storres
        intervalResultsList = []
4366 222 storres
        intervalResultsList.append((lb, ub))
4367 222 storres
        #### Check roots.
4368 222 storres
        rootsResultsList = []
4369 222 storres
        for iRoot in iRootsSet:
4370 222 storres
            specificRootResultsList = []
4371 222 storres
            failingBounds           = []
4372 222 storres
            # Root qualifies for modular equation, test it for hardness to round.
4373 222 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + iRoot) / toIntegerFactor)
4374 222 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
4375 222 storres
            #print scalingFunction
4376 222 storres
            scaledHardToRoundCaseAsFloat = \
4377 222 storres
                scalingFunction(hardToRoundCaseAsFloat)
4378 222 storres
            print "Candidate HTRNc at x =", \
4379 222 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
4380 222 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
4381 222 storres
                           function,
4382 222 storres
                           2^-(targetHardnessToRound),
4383 222 storres
                           RRR,
4384 222 storres
                           targetPlusOnePrecRF,
4385 222 storres
                           quasiExactRF):
4386 222 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
4387 222 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
4388 222 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
4389 222 storres
                    print "Found in interval."
4390 222 storres
                else:
4391 222 storres
                    print "Found out of interval."
4392 222 storres
                # Check the i root is within the i bound.
4393 222 storres
                if abs(iRoot) > iBound:
4394 222 storres
                    print "IRoot", iRoot, "is out of bounds for modular equation."
4395 222 storres
                    print "i bound:", iBound
4396 222 storres
                    failingBounds.append('i')
4397 222 storres
                    failingBounds.append(iRoot)
4398 222 storres
                    failingBounds.append(iBound)
4399 222 storres
                if len(failingBounds) > 0:
4400 222 storres
                    specificRootResultsList.append(failingBounds)
4401 222 storres
            else: # From slz_is_htrn...
4402 229 storres
                print "is not an HTRN case for integer value:", iRoot
4403 222 storres
            if len(specificRootResultsList) > 0:
4404 222 storres
                rootsResultsList.append(specificRootResultsList)
4405 222 storres
        if len(rootsResultsList) > 0:
4406 222 storres
            intervalResultsList.append(rootsResultsList)
4407 222 storres
        ### Check if a non null resultant was found. If not shrink the interval.
4408 222 storres
        if not hasNonNullResultant:
4409 222 storres
            print "Only null resultants for this reduction, shrinking interval."
4410 222 storres
            resultCondFailed      =  True
4411 222 storres
            resultCondFailedCount += 1
4412 222 storres
            ### Shrink interval for next iteration.
4413 222 storres
            ub = lb + bw * onlyNullResultantsShrink
4414 222 storres
            if ub > sdub:
4415 222 storres
                ub = sdub
4416 222 storres
            nbw = 0
4417 222 storres
            continue
4418 222 storres
        #### An intervalResultsList has at least the bounds.
4419 222 storres
        globalResultsList.append(intervalResultsList)
4420 222 storres
        #### Compute an incremented width for next upper bound, only
4421 222 storres
        #    if not Coppersmith condition nor resultant condition
4422 222 storres
        #    failed at the previous run.
4423 222 storres
        if not coppCondFailed and not resultCondFailed:
4424 222 storres
            nbw = noErrorIntervalStretch * bw
4425 222 storres
        else:
4426 222 storres
            nbw = bw
4427 222 storres
        ##### Reset the failure flags. They will be raised
4428 222 storres
        #     again if needed.
4429 222 storres
        coppCondFailed   = False
4430 222 storres
        resultCondFailed = False
4431 222 storres
        #### For next iteration (at end of loop)
4432 222 storres
        #print "nbw:", nbw
4433 222 storres
        lb  = ub
4434 222 storres
        ub += nbw
4435 222 storres
        if ub > sdub:
4436 222 storres
            ub = sdub
4437 222 storres
        print
4438 222 storres
    # End while True
4439 222 storres
    ## Main loop just ended.
4440 222 storres
    globalWallTime = walltime(wallTimeStart)
4441 222 storres
    globalCpuTime  = cputime(cpuTimeStart)
4442 222 storres
    ## Output results
4443 222 storres
    print ; print "Intervals and HTRNs" ; print
4444 222 storres
    for intervalResultsList in globalResultsList:
4445 222 storres
        intervalResultString = "[" + str(intervalResultsList[0][0]) +\
4446 222 storres
                               "," + str(intervalResultsList[0][1])  + "]"
4447 222 storres
        print intervalResultString,
4448 222 storres
        if len(intervalResultsList) > 1:
4449 222 storres
            rootsResultsList = intervalResultsList[1]
4450 222 storres
            specificRootResultIndex = 0
4451 222 storres
            for specificRootResultsList in rootsResultsList:
4452 222 storres
                if specificRootResultIndex == 0:
4453 222 storres
                    print "\t", specificRootResultsList[0],
4454 222 storres
                else:
4455 222 storres
                    print " " * len(intervalResultString), "\t", \
4456 222 storres
                          specificRootResultsList[0],
4457 222 storres
                if len(specificRootResultsList) > 1:
4458 222 storres
                    print specificRootResultsList[1]
4459 222 storres
                specificRootResultIndex += 1
4460 222 storres
        print ; print
4461 222 storres
    #print globalResultsList
4462 222 storres
    #
4463 222 storres
    print "Timers and counters"
4464 222 storres
    print
4465 222 storres
    print "Number of iterations:", iterCount
4466 222 storres
    print "Taylor condition failures:", taylCondFailedCount
4467 222 storres
    print "Coppersmith condition failures:", coppCondFailedCount
4468 222 storres
    print "Resultant condition failures:", resultCondFailedCount
4469 222 storres
    print "Iterations count: ", iterCount
4470 222 storres
    print "Number of intervals:", len(globalResultsList)
4471 222 storres
    print "Number of basis constructions:", basisConstructionsCount
4472 222 storres
    print "Total CPU time spent in basis constructions:", \
4473 222 storres
        basisConstructionsFullTime
4474 222 storres
    if basisConstructionsCount != 0:
4475 222 storres
        print "Average basis construction CPU time:", \
4476 222 storres
            basisConstructionsFullTime/basisConstructionsCount
4477 222 storres
    print "Number of reductions:", reductionsCount
4478 222 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
4479 222 storres
    if reductionsCount != 0:
4480 222 storres
        print "Average reduction CPU time:", \
4481 222 storres
            reductionsFullTime/reductionsCount
4482 222 storres
    print "Number of resultants computation rounds:", \
4483 222 storres
        resultantsComputationsCount
4484 222 storres
    print "Total CPU time spent in resultants computation rounds:", \
4485 222 storres
        resultantsComputationsFullTime
4486 222 storres
    if resultantsComputationsCount != 0:
4487 222 storres
        print "Average resultants computation round CPU time:", \
4488 222 storres
            resultantsComputationsFullTime/resultantsComputationsCount
4489 222 storres
    print "Number of root finding rounds:", rootsComputationsCount
4490 222 storres
    print "Total CPU time spent in roots finding rounds:", \
4491 222 storres
        rootsComputationsFullTime
4492 222 storres
    if rootsComputationsCount != 0:
4493 222 storres
        print "Average roots finding round CPU time:", \
4494 222 storres
            rootsComputationsFullTime/rootsComputationsCount
4495 222 storres
    print "Global Wall time:", globalWallTime
4496 222 storres
    print "Global CPU time:", globalCpuTime
4497 222 storres
    ## Output counters
4498 222 storres
# End srs_runSLZ-v06
4499 246 storres
sys.stderr.write("\t...sage Runtime SLZ loaded.\n")