Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (155,08 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 213 storres
print "sageRationalOperations loading..."
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 213 storres
    ## Compute the scaled function and the degree, in their Sollya version
100 213 storres
    #  once for all.
101 213 storres
    (scaledf, sdlb, sdub, silb, siub) = \
102 213 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
103 213 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
104 213 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
105 213 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
106 213 storres
    #
107 213 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
108 213 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
109 213 storres
    (unscalingFunction, scalingFunction) = \
110 213 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
111 213 storres
    #print scalingFunction, unscalingFunction
112 213 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
113 213 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
114 213 storres
    if internalSollyaPrec < 192:
115 213 storres
        internalSollyaPrec = 192
116 213 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
117 213 storres
    print "Sollya internal precision:", internalSollyaPrec
118 213 storres
    ## Some variables.
119 213 storres
    ### General variables
120 213 storres
    lb                  = sdlb
121 213 storres
    ub                  = sdub
122 213 storres
    nbw                 = 0
123 213 storres
    intervalUlp         = ub.ulp()
124 213 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
125 213 storres
    ic                  = 0
126 213 storres
    icAsInt             = 0    # Set from ic.
127 213 storres
    solutionsSet        = set()
128 213 storres
    tsErrorWidth        = []
129 213 storres
    csErrorVectors      = []
130 213 storres
    csVectorsResultants = []
131 213 storres
    floatP              = 0  # Taylor polynomial.
132 213 storres
    floatPcv            = 0  # Ditto with variable change.
133 213 storres
    intvl               = "" # Taylor interval
134 213 storres
    terr                = 0  # Taylor error.
135 213 storres
    iterCount = 0
136 213 storres
    htrnSet = set()
137 213 storres
    ### Timers and counters.
138 213 storres
    wallTimeStart                   = 0
139 213 storres
    cpuTimeStart                    = 0
140 213 storres
    taylCondFailedCount             = 0
141 213 storres
    coppCondFailedCount             = 0
142 213 storres
    resultCondFailedCount           = 0
143 213 storres
    coppCondFailed                  = False
144 213 storres
    resultCondFailed                = False
145 213 storres
    globalResultsList               = []
146 213 storres
    basisConstructionsCount         = 0
147 213 storres
    basisConstructionsFullTime      = 0
148 213 storres
    basisConstructionTime           = 0
149 213 storres
    reductionsCount                 = 0
150 213 storres
    reductionsFullTime              = 0
151 213 storres
    reductionTime                   = 0
152 213 storres
    resultantsComputationsCount     = 0
153 213 storres
    resultantsComputationsFullTime  = 0
154 213 storres
    resultantsComputationTime       = 0
155 213 storres
    rootsComputationsCount          = 0
156 213 storres
    rootsComputationsFullTime       = 0
157 213 storres
    rootsComputationTime            = 0
158 213 storres
    print
159 213 storres
    ## Global times are started here.
160 213 storres
    wallTimeStart                   = walltime()
161 213 storres
    cpuTimeStart                    = cputime()
162 213 storres
    ## Main loop.
163 213 storres
    while True:
164 213 storres
        if lb >= sdub:
165 213 storres
            print "Lower bound reached upper bound."
166 213 storres
            break
167 213 storres
        if iterCount == maxIter:
168 213 storres
            print "Reached maxIter. Aborting"
169 213 storres
            break
170 213 storres
        iterCount += 1
171 213 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
172 213 storres
            "log2(numbers)."
173 213 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
174 213 storres
        prceSo = slz_compute_polynomial_and_interval(scaledfSo,
175 213 storres
                                                     degreeSo,
176 213 storres
                                                     lb,
177 213 storres
                                                     ub,
178 213 storres
                                                     polyApproxAccur)
179 213 storres
        ### Convert back the data into Sage space.
180 213 storres
        (floatP, floatPcv, intvl, ic, terr) = \
181 213 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
182 213 storres
                                                 prceSo[1], prceSo[2],
183 213 storres
                                                 prceSo[3]))
184 213 storres
        intvl = RRIF(intvl)
185 213 storres
        ## Clean-up Sollya stuff.
186 213 storres
        for elem in prceSo:
187 213 storres
            sollya_lib_clear_obj(elem)
188 213 storres
        #print  floatP, floatPcv, intvl, ic, terr
189 213 storres
        #print floatP
190 213 storres
        #print intvl.endpoints()[0].n(), \
191 213 storres
        #      ic.n(),
192 213 storres
        #intvl.endpoints()[1].n()
193 213 storres
        ### Check returned data.
194 213 storres
        #### Is approximation error OK?
195 213 storres
        if terr > polyApproxAccur:
196 213 storres
            exceptionErrorMess  = \
197 213 storres
                "Approximation failed - computed error:" + \
198 213 storres
                str(terr) + " - target error: "
199 213 storres
            exceptionErrorMess += \
200 213 storres
                str(polyApproxAccur) + ". Aborting!"
201 213 storres
            raise Exception(exceptionErrorMess)
202 213 storres
        #### Is lower bound OK?
203 213 storres
        if lb != intvl.endpoints()[0]:
204 213 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
205 213 storres
                               str(lb) + ". Aborting!"
206 213 storres
            raise Exception(exceptionErrorMess)
207 213 storres
        #### Set upper bound.
208 213 storres
        if ub > intvl.endpoints()[1]:
209 213 storres
            ub = intvl.endpoints()[1]
210 213 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
211 213 storres
            "log2(numbers)."
212 213 storres
            taylCondFailedCount += 1
213 213 storres
        #### Is interval not degenerate?
214 213 storres
        if lb >= ub:
215 213 storres
            exceptionErrorMess = "Degenerate interval: " + \
216 213 storres
                                "lowerBound(" + str(lb) +\
217 213 storres
                                ")>= upperBound(" + str(ub) + \
218 213 storres
                                "). Aborting!"
219 213 storres
            raise Exception(exceptionErrorMess)
220 213 storres
        #### Is interval center ok?
221 213 storres
        if ic <= lb or ic >= ub:
222 213 storres
            exceptionErrorMess =  "Invalid interval center for " + \
223 213 storres
                                str(lb) + ',' + str(ic) + ',' +  \
224 213 storres
                                str(ub) + ". Aborting!"
225 213 storres
            raise Exception(exceptionErrorMess)
226 213 storres
        ##### Current interval width and reset future interval width.
227 213 storres
        bw = ub - lb
228 213 storres
        nbw = 0
229 213 storres
        icAsInt = int(ic * toIntegerFactor)
230 213 storres
        #### The following ratio is always >= 1. In case we may want to
231 213 storres
        #    enlarge the interval
232 213 storres
        curTaylErrRat = polyApproxAccur / terr
233 213 storres
        ### Make the  integral transformations.
234 213 storres
        #### Bounds and interval center.
235 213 storres
        intIc = int(ic * toIntegerFactor)
236 213 storres
        intLb = int(lb * toIntegerFactor) - intIc
237 213 storres
        intUb = int(ub * toIntegerFactor) - intIc
238 213 storres
        #
239 213 storres
        #### Polynomials
240 213 storres
        basisConstructionTime         = cputime()
241 213 storres
        ##### To a polynomial with rational coefficients with rational arguments
242 213 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
243 213 storres
        ##### To a polynomial with rational coefficients with integer arguments
244 213 storres
        ratIntP = \
245 213 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
246 213 storres
        #####  Ultimately a multivariate polynomial with integer coefficients
247 213 storres
        #      with integer arguments.
248 213 storres
        coppersmithTuple = \
249 213 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
250 213 storres
                                                        precision,
251 213 storres
                                                        targetHardnessToRound,
252 213 storres
                                                        i, t)
253 213 storres
        #### Recover Coppersmith information.
254 213 storres
        intIntP = coppersmithTuple[0]
255 213 storres
        N = coppersmithTuple[1]
256 213 storres
        nAtAlpha = N^alpha
257 213 storres
        tBound = coppersmithTuple[2]
258 213 storres
        leastCommonMultiple = coppersmithTuple[3]
259 213 storres
        iBound = max(abs(intLb),abs(intUb))
260 213 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
261 213 storres
        basisConstructionsCount           += 1
262 213 storres
        reductionTime                     = cputime()
263 213 storres
        #### Compute the reduced polynomials.
264 213 storres
        ccReducedPolynomialsList =  \
265 213 storres
            slz_compute_coppersmith_reduced_polynomials_with_lattice_volume(intIntP,
266 213 storres
                                                        alpha,
267 213 storres
                                                        N,
268 213 storres
                                                        iBound,
269 213 storres
                                                        tBound)
270 213 storres
        if ccReducedPolynomialsList is None:
271 213 storres
            raise Exception("Reduction failed.")
272 213 storres
        reductionsFullTime    += cputime(reductionTime)
273 213 storres
        reductionsCount       += 1
274 213 storres
        if len(ccReducedPolynomialsList) < 2:
275 213 storres
            print "Nothing to form resultants with."
276 213 storres
            print
277 213 storres
            coppCondFailedCount += 1
278 213 storres
            coppCondFailed = True
279 213 storres
            ##### Apply a different shrink factor according to
280 213 storres
            #  the number of compliant polynomials.
281 213 storres
            if len(ccReducedPolynomialsList) == 0:
282 213 storres
                ub = lb + bw * noCoppersmithIntervalShrink
283 213 storres
            else: # At least one compliant polynomial.
284 213 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
285 213 storres
            if ub > sdub:
286 213 storres
                ub = sdub
287 213 storres
            if lb == ub:
288 213 storres
                raise Exception("Cant shrink interval \
289 213 storres
                anymore to get Coppersmith condition.")
290 213 storres
            nbw = 0
291 213 storres
            continue
292 213 storres
        #### We have at least two polynomials.
293 213 storres
        #    Let us try to compute resultants.
294 213 storres
        #    For each resultant computed, go for the solutions.
295 213 storres
        ##### Build the pairs list.
296 213 storres
        polyPairsList           = []
297 213 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
298 213 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
299 213 storres
                                         len(ccReducedPolynomialsList)):
300 213 storres
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
301 213 storres
                                      ccReducedPolynomialsList[polyInnerIndex]))
302 213 storres
        #### Actual root search.
303 213 storres
        rootsSet            = set()
304 213 storres
        hasNonNullResultant = False
305 213 storres
        for polyPair in polyPairsList:
306 213 storres
            if hasNonNullResultant:
307 213 storres
                break
308 213 storres
            resultantsComputationTime   = cputime()
309 213 storres
            currentResultantI = \
310 213 storres
                slz_resultant(polyPair[0],
311 213 storres
                              polyPair[1],
312 213 storres
                              t)
313 213 storres
            resultantsComputationsCount    += 1
314 213 storres
            if currentResultantI is None:
315 213 storres
                resultantsComputationsFullTime +=  \
316 213 storres
                    cputime(resultantsComputationTime)
317 213 storres
                print "Nul resultant"
318 213 storres
                continue # Next polyPair.
319 213 storres
            currentResultantT = \
320 213 storres
                slz_resultant(polyPair[0],
321 213 storres
                              polyPair[1],
322 213 storres
                              i)
323 213 storres
            resultantsComputationsFullTime += cputime(resultantsComputationTime)
324 213 storres
            resultantsComputationsCount    += 1
325 213 storres
            if currentResultantT is None:
326 213 storres
                print "Nul resultant"
327 213 storres
                continue # Next polyPair.
328 213 storres
            else:
329 213 storres
                hasNonNullResultant = True
330 213 storres
            #### We have a non null resultants pair. From now on, whatever the
331 213 storres
            #    root search yields, no extra root search is necessary.
332 213 storres
            #### A constant resultant leads to no root. Root search is done.
333 213 storres
            if currentResultantI.degree() < 1:
334 213 storres
                print "Resultant is constant:", currentResultantI
335 213 storres
                break # Next polyPair and should break.
336 213 storres
            if currentResultantT.degree() < 1:
337 213 storres
                print "Resultant is constant:", currentResultantT
338 213 storres
                break # Next polyPair and should break.
339 213 storres
            #### Actual roots computation.
340 213 storres
            rootsComputationTime       = cputime()
341 213 storres
            ##### Compute i roots
342 213 storres
            iRootsList = Zi(currentResultantI).roots()
343 213 storres
            rootsComputationsCount      +=  1
344 213 storres
            if len(iRootsList) == 0:
345 213 storres
                rootsComputationsFullTime   =   cputime(rootsComputationTime)
346 213 storres
                print "No roots in \"i\"."
347 213 storres
                break # No roots in i.
348 213 storres
            tRootsList = Zt(currentResultantT).roots()
349 213 storres
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
350 213 storres
            rootsComputationsCount      +=  1
351 213 storres
            if len(tRootsList) == 0:
352 213 storres
                print "No roots in \"t\"."
353 213 storres
                break # No roots in i.
354 213 storres
            ##### For each iRoot, get a tRoot and check against the polynomials.
355 213 storres
            for iRoot in iRootsList:
356 213 storres
                ####### Roots returned by roots() are (value, multiplicity)
357 213 storres
                #       tuples.
358 213 storres
                #print "iRoot:", iRoot
359 213 storres
                for tRoot in tRootsList:
360 213 storres
                ###### Use the tRoot against each polynomial, alternatively.
361 213 storres
                    if polyPair[0](iRoot[0],tRoot[0]) != 0:
362 213 storres
                        continue
363 213 storres
                    if polyPair[1](iRoot[0],tRoot[0]) != 0:
364 213 storres
                        continue
365 213 storres
                    rootsSet.add((iRoot[0], tRoot[0]))
366 213 storres
            # End of roots computation.
367 213 storres
        # End loop for polyPair in polyParsList.  Will break at next iteration.
368 213 storres
        # since a non null resultant was found.
369 213 storres
        #### Prepare for results for the current interval..
370 213 storres
        intervalResultsList = []
371 213 storres
        intervalResultsList.append((lb, ub))
372 213 storres
        #### Check roots.
373 213 storres
        rootsResultsList = []
374 213 storres
        for root in rootsSet:
375 213 storres
            specificRootResultsList = []
376 213 storres
            failingBounds = []
377 213 storres
            intIntPdivN = intIntP(root[0], root[1]) / N
378 213 storres
            if int(intIntPdivN) != intIntPdivN:
379 213 storres
                continue # Next root
380 213 storres
            # Root qualifies for modular equation, test it for hardness to round.
381 213 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + root[0]) / toIntegerFactor)
382 213 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
383 213 storres
            #print scalingFunction
384 213 storres
            scaledHardToRoundCaseAsFloat = \
385 213 storres
                scalingFunction(hardToRoundCaseAsFloat)
386 213 storres
            print "Candidate HTRNc at x =", \
387 213 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
388 213 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
389 213 storres
                           function,
390 213 storres
                           2^-(targetHardnessToRound),
391 213 storres
                           RRR):
392 213 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
393 213 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
394 213 storres
                    print "Found in interval."
395 213 storres
                else:
396 213 storres
                    print "Found out of interval."
397 213 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
398 213 storres
                # Check the root is in the bounds
399 213 storres
                if abs(root[0]) > iBound or abs(root[1]) > tBound:
400 213 storres
                    print "Root", root, "is out of bounds for modular equation."
401 213 storres
                    if abs(root[0]) > iBound:
402 213 storres
                        print "root[0]:", root[0]
403 213 storres
                        print "i bound:", iBound
404 213 storres
                        failingBounds.append('i')
405 213 storres
                        failingBounds.append(root[0])
406 213 storres
                        failingBounds.append(iBound)
407 213 storres
                    if abs(root[1]) > tBound:
408 213 storres
                        print "root[1]:", root[1]
409 213 storres
                        print "t bound:", tBound
410 213 storres
                        failingBounds.append('t')
411 213 storres
                        failingBounds.append(root[1])
412 213 storres
                        failingBounds.append(tBound)
413 213 storres
                if len(failingBounds) > 0:
414 213 storres
                    specificRootResultsList.append(failingBounds)
415 213 storres
            else: # From slz_is_htrn...
416 213 storres
                print "is not an HTRN case."
417 213 storres
            if len(specificRootResultsList) > 0:
418 213 storres
                rootsResultsList.append(specificRootResultsList)
419 213 storres
        if len(rootsResultsList) > 0:
420 213 storres
            intervalResultsList.append(rootsResultsList)
421 213 storres
        ### Check if a non null resultant was found. If not shrink the interval.
422 213 storres
        if not hasNonNullResultant:
423 213 storres
            print "Only null resultants for this reduction, shrinking interval."
424 213 storres
            resultCondFailed      =  True
425 213 storres
            resultCondFailedCount += 1
426 213 storres
            ### Shrink interval for next iteration.
427 213 storres
            ub = lb + bw * onlyNullResultantsShrink
428 213 storres
            if ub > sdub:
429 213 storres
                ub = sdub
430 213 storres
            nbw = 0
431 213 storres
            continue
432 213 storres
        #### An intervalResultsList has at least the bounds.
433 213 storres
        globalResultsList.append(intervalResultsList)
434 213 storres
        #### Compute an incremented width for next upper bound, only
435 213 storres
        #    if not Coppersmith condition nor resultant condition
436 213 storres
        #    failed at the previous run.
437 213 storres
        if not coppCondFailed and not resultCondFailed:
438 213 storres
            nbw = noErrorIntervalStretch * bw
439 213 storres
        else:
440 213 storres
            nbw = bw
441 213 storres
        ##### Reset the failure flags. They will be raised
442 213 storres
        #     again if needed.
443 213 storres
        coppCondFailed   = False
444 213 storres
        resultCondFailed = False
445 213 storres
        #### For next iteration (at end of loop)
446 213 storres
        #print "nbw:", nbw
447 213 storres
        lb  = ub
448 213 storres
        ub += nbw
449 213 storres
        if ub > sdub:
450 213 storres
            ub = sdub
451 213 storres
        print
452 213 storres
    # End while True
453 213 storres
    ## Main loop just ended.
454 213 storres
    globalWallTime = walltime(wallTimeStart)
455 213 storres
    globalCpuTime  = cputime(cpuTimeStart)
456 213 storres
    ## Output results
457 213 storres
    print ; print "Intervals and HTRNs" ; print
458 213 storres
    for intervalResultsList in globalResultsList:
459 222 storres
        intervalResultString = "[" + str(intervalResultsList[0][0]) +\
460 222 storres
                               "," + str(intervalResultsList[0][1])  + "]"
461 222 storres
        print intervalResultString,
462 213 storres
        if len(intervalResultsList) > 1:
463 213 storres
            rootsResultsList = intervalResultsList[1]
464 222 storres
            specificRootResultIndex = 0
465 213 storres
            for specificRootResultsList in rootsResultsList:
466 222 storres
                if specificRootResultIndex == 0:
467 222 storres
                    print "\t", specificRootResultsList[0],
468 222 storres
                else:
469 222 storres
                    print " " * len(intervalResultString), "\t", \
470 222 storres
                          specificRootResultsList[0],
471 213 storres
                if len(specificRootResultsList) > 1:
472 222 storres
                    print specificRootResultsList[1]
473 222 storres
                specificRootResultIndex += 1
474 213 storres
        print ; print
475 213 storres
    #print globalResultsList
476 213 storres
    #
477 213 storres
    print "Timers and counters"
478 213 storres
    print
479 213 storres
    print "Number of iterations:", iterCount
480 213 storres
    print "Taylor condition failures:", taylCondFailedCount
481 213 storres
    print "Coppersmith condition failures:", coppCondFailedCount
482 213 storres
    print "Resultant condition failures:", resultCondFailedCount
483 213 storres
    print "Iterations count: ", iterCount
484 213 storres
    print "Number of intervals:", len(globalResultsList)
485 213 storres
    print "Number of basis constructions:", basisConstructionsCount
486 213 storres
    print "Total CPU time spent in basis constructions:", \
487 213 storres
        basisConstructionsFullTime
488 213 storres
    if basisConstructionsCount != 0:
489 213 storres
        print "Average basis construction CPU time:", \
490 213 storres
            basisConstructionsFullTime/basisConstructionsCount
491 213 storres
    print "Number of reductions:", reductionsCount
492 213 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
493 213 storres
    if reductionsCount != 0:
494 213 storres
        print "Average reduction CPU time:", \
495 213 storres
            reductionsFullTime/reductionsCount
496 213 storres
    print "Number of resultants computation rounds:", \
497 213 storres
        resultantsComputationsCount
498 213 storres
    print "Total CPU time spent in resultants computation rounds:", \
499 213 storres
        resultantsComputationsFullTime
500 213 storres
    if resultantsComputationsCount != 0:
501 213 storres
        print "Average resultants computation round CPU time:", \
502 213 storres
            resultantsComputationsFullTime/resultantsComputationsCount
503 213 storres
    print "Number of root finding rounds:", rootsComputationsCount
504 213 storres
    print "Total CPU time spent in roots finding rounds:", \
505 213 storres
        rootsComputationsFullTime
506 213 storres
    if rootsComputationsCount != 0:
507 213 storres
        print "Average roots finding round CPU time:", \
508 213 storres
            rootsComputationsFullTime/rootsComputationsCount
509 213 storres
    print "Global Wall time:", globalWallTime
510 213 storres
    print "Global CPU time:", globalCpuTime
511 213 storres
    ## Output counters
512 213 storres
# End srs_compute_lattice_volume
513 213 storres
514 213 storres
"""
515 194 storres
SLZ runtime function.
516 194 storres
"""
517 194 storres
518 194 storres
def srs_run_SLZ_v01(inputFunction,
519 194 storres
                    inputLowerBound,
520 194 storres
                    inputUpperBound,
521 194 storres
                    alpha,
522 194 storres
                    degree,
523 194 storres
                    precision,
524 194 storres
                    emin,
525 194 storres
                    emax,
526 194 storres
                    targetHardnessToRound,
527 194 storres
                    debug = False):
528 194 storres
529 194 storres
    if debug:
530 194 storres
        print "Function                :", inputFunction
531 194 storres
        print "Lower bound             :", inputLowerBound
532 194 storres
        print "Upper bounds            :", inputUpperBound
533 194 storres
        print "Alpha                   :", alpha
534 194 storres
        print "Degree                  :", degree
535 194 storres
        print "Precision               :", precision
536 194 storres
        print "Emin                    :", emin
537 194 storres
        print "Emax                    :", emax
538 194 storres
        print "Target hardness-to-round:", targetHardnessToRound
539 194 storres
        print
540 194 storres
    ## Important constants.
541 194 storres
    ### Stretch the interval if no error happens.
542 194 storres
    noErrorIntervalStretch = 1 + 2^(-5)
543 194 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
544 194 storres
    #   by the following factor.
545 194 storres
    noCoppersmithIntervalShrink = 1/2
546 194 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
547 194 storres
    #   shrink the interval by the following factor.
548 194 storres
    oneCoppersmithIntervalShrink = 3/4
549 194 storres
    #### If only null resultants are found, shrink the interval by the
550 194 storres
    #    following factor.
551 194 storres
    onlyNullResultantsShrink     = 3/4
552 194 storres
    ## Structures.
553 194 storres
    RRR         = RealField(precision)
554 194 storres
    RRIF        = RealIntervalField(precision)
555 194 storres
    ## Converting input bound into the "right" field.
556 194 storres
    lowerBound = RRR(inputLowerBound)
557 194 storres
    upperBound = RRR(inputUpperBound)
558 194 storres
    ## Before going any further, check domain and image binade conditions.
559 194 storres
    print inputFunction(1).n()
560 206 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
561 206 storres
    if output is None:
562 206 storres
        print "Invalid domain/image binades. Domain:",\
563 206 storres
        lowerBound, upperBound, "Images:", \
564 206 storres
        inputFunction(lowerBound), inputFunction(upperBound)
565 206 storres
        raise Exception("Invalid domain/image binades.")
566 206 storres
    lb = output[0] ; ub = output[1]
567 206 storres
    if lb is None or lb != lowerBound or ub != upperBound:
568 194 storres
        print "lb:", lb, " - ub:", ub
569 194 storres
        print "Invalid domain/image binades. Domain:",\
570 194 storres
        lowerBound, upperBound, "Images:", \
571 194 storres
        inputFunction(lowerBound), inputFunction(upperBound)
572 194 storres
        raise Exception("Invalid domain/image binades.")
573 194 storres
    #
574 194 storres
    ## Progam initialization
575 194 storres
    ### Approximation polynomial accuracy and hardness to round.
576 194 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
577 194 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
578 194 storres
    ### Significand to integer conversion ratio.
579 194 storres
    toIntegerFactor           = 2^(precision-1)
580 194 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
581 194 storres
    ### Variables and rings for polynomials and root searching.
582 194 storres
    i=var('i')
583 194 storres
    t=var('t')
584 194 storres
    inputFunctionVariable = inputFunction.variables()[0]
585 194 storres
    function = inputFunction.subs({inputFunctionVariable:i})
586 194 storres
    #  Polynomial Rings over the integers, for root finding.
587 194 storres
    Zi = ZZ[i]
588 194 storres
    Zt = ZZ[t]
589 194 storres
    Zit = ZZ[i,t]
590 194 storres
    ## Number of iterations limit.
591 194 storres
    maxIter = 100000
592 194 storres
    #
593 194 storres
    ## Compute the scaled function and the degree, in their Sollya version
594 194 storres
    #  once for all.
595 194 storres
    (scaledf, sdlb, sdub, silb, siub) = \
596 194 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
597 194 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
598 194 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
599 194 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
600 194 storres
    #
601 194 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
602 194 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
603 194 storres
    (unscalingFunction, scalingFunction) = \
604 194 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
605 194 storres
    #print scalingFunction, unscalingFunction
606 194 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
607 194 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
608 194 storres
    if internalSollyaPrec < 192:
609 194 storres
        internalSollyaPrec = 192
610 194 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
611 194 storres
    print "Sollya internal precision:", internalSollyaPrec
612 194 storres
    ## Some variables.
613 194 storres
    ### General variables
614 194 storres
    lb                  = sdlb
615 194 storres
    ub                  = sdub
616 194 storres
    nbw                 = 0
617 194 storres
    intervalUlp         = ub.ulp()
618 194 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
619 194 storres
    ic                  = 0
620 194 storres
    icAsInt             = 0    # Set from ic.
621 194 storres
    solutionsSet        = set()
622 194 storres
    tsErrorWidth        = []
623 194 storres
    csErrorVectors      = []
624 194 storres
    csVectorsResultants = []
625 194 storres
    floatP              = 0  # Taylor polynomial.
626 194 storres
    floatPcv            = 0  # Ditto with variable change.
627 194 storres
    intvl               = "" # Taylor interval
628 194 storres
    terr                = 0  # Taylor error.
629 194 storres
    iterCount = 0
630 194 storres
    htrnSet = set()
631 194 storres
    ### Timers and counters.
632 194 storres
    wallTimeStart                   = 0
633 194 storres
    cpuTimeStart                    = 0
634 194 storres
    taylCondFailedCount             = 0
635 194 storres
    coppCondFailedCount             = 0
636 194 storres
    resultCondFailedCount           = 0
637 194 storres
    coppCondFailed                  = False
638 194 storres
    resultCondFailed                = False
639 194 storres
    globalResultsList               = []
640 194 storres
    basisConstructionsCount         = 0
641 194 storres
    basisConstructionsFullTime      = 0
642 194 storres
    basisConstructionTime           = 0
643 194 storres
    reductionsCount                 = 0
644 194 storres
    reductionsFullTime              = 0
645 194 storres
    reductionTime                   = 0
646 194 storres
    resultantsComputationsCount     = 0
647 194 storres
    resultantsComputationsFullTime  = 0
648 194 storres
    resultantsComputationTime       = 0
649 194 storres
    rootsComputationsCount          = 0
650 194 storres
    rootsComputationsFullTime       = 0
651 194 storres
    rootsComputationTime            = 0
652 194 storres
    print
653 194 storres
    ## Global times are started here.
654 194 storres
    wallTimeStart                   = walltime()
655 194 storres
    cpuTimeStart                    = cputime()
656 194 storres
    ## Main loop.
657 194 storres
    while True:
658 194 storres
        if lb >= sdub:
659 194 storres
            print "Lower bound reached upper bound."
660 194 storres
            break
661 194 storres
        if iterCount == maxIter:
662 194 storres
            print "Reached maxIter. Aborting"
663 194 storres
            break
664 194 storres
        iterCount += 1
665 194 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
666 194 storres
            "log2(numbers)."
667 194 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
668 194 storres
        prceSo = slz_compute_polynomial_and_interval(scaledfSo,
669 194 storres
                                                     degreeSo,
670 194 storres
                                                     lb,
671 194 storres
                                                     ub,
672 194 storres
                                                     polyApproxAccur)
673 194 storres
        ### Convert back the data into Sage space.
674 194 storres
        (floatP, floatPcv, intvl, ic, terr) = \
675 194 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
676 194 storres
                                                 prceSo[1], prceSo[2],
677 194 storres
                                                 prceSo[3]))
678 194 storres
        intvl = RRIF(intvl)
679 194 storres
        ## Clean-up Sollya stuff.
680 194 storres
        for elem in prceSo:
681 194 storres
            sollya_lib_clear_obj(elem)
682 194 storres
        #print  floatP, floatPcv, intvl, ic, terr
683 194 storres
        #print floatP
684 194 storres
        #print intvl.endpoints()[0].n(), \
685 194 storres
        #      ic.n(),
686 194 storres
        #intvl.endpoints()[1].n()
687 194 storres
        ### Check returned data.
688 194 storres
        #### Is approximation error OK?
689 194 storres
        if terr > polyApproxAccur:
690 194 storres
            exceptionErrorMess  = \
691 194 storres
                "Approximation failed - computed error:" + \
692 194 storres
                str(terr) + " - target error: "
693 194 storres
            exceptionErrorMess += \
694 194 storres
                str(polyApproxAccur) + ". Aborting!"
695 194 storres
            raise Exception(exceptionErrorMess)
696 194 storres
        #### Is lower bound OK?
697 194 storres
        if lb != intvl.endpoints()[0]:
698 194 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
699 194 storres
                               str(lb) + ". Aborting!"
700 194 storres
            raise Exception(exceptionErrorMess)
701 194 storres
        #### Set upper bound.
702 194 storres
        if ub > intvl.endpoints()[1]:
703 194 storres
            ub = intvl.endpoints()[1]
704 194 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
705 194 storres
            "log2(numbers)."
706 194 storres
            taylCondFailedCount += 1
707 194 storres
        #### Is interval not degenerate?
708 194 storres
        if lb >= ub:
709 194 storres
            exceptionErrorMess = "Degenerate interval: " + \
710 194 storres
                                "lowerBound(" + str(lb) +\
711 194 storres
                                ")>= upperBound(" + str(ub) + \
712 194 storres
                                "). Aborting!"
713 194 storres
            raise Exception(exceptionErrorMess)
714 194 storres
        #### Is interval center ok?
715 194 storres
        if ic <= lb or ic >= ub:
716 194 storres
            exceptionErrorMess =  "Invalid interval center for " + \
717 194 storres
                                str(lb) + ',' + str(ic) + ',' +  \
718 194 storres
                                str(ub) + ". Aborting!"
719 194 storres
            raise Exception(exceptionErrorMess)
720 194 storres
        ##### Current interval width and reset future interval width.
721 194 storres
        bw = ub - lb
722 194 storres
        nbw = 0
723 194 storres
        icAsInt = int(ic * toIntegerFactor)
724 194 storres
        #### The following ratio is always >= 1. In case we may want to
725 194 storres
        #  enlarge the interval
726 194 storres
        curTaylErrRat = polyApproxAccur / terr
727 194 storres
        ## Make the  integral transformations.
728 194 storres
        ### First for interval center and bounds.
729 194 storres
        intIc = int(ic * toIntegerFactor)
730 194 storres
        intLb = int(lb * toIntegerFactor) - intIc
731 194 storres
        intUb = int(ub * toIntegerFactor) - intIc
732 194 storres
        #
733 194 storres
        #### For polynomials
734 194 storres
        basisConstructionTime         = cputime()
735 194 storres
        ##### To a polynomial with rational coefficients with rational arguments
736 194 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
737 194 storres
        ##### To a polynomial with rational coefficients with integer arguments
738 194 storres
        ratIntP = \
739 194 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
740 194 storres
        #####  Ultimately a polynomial with integer coefficients with integer
741 194 storres
        #      arguments.
742 194 storres
        coppersmithTuple = \
743 194 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
744 194 storres
                                                        precision,
745 194 storres
                                                        targetHardnessToRound,
746 194 storres
                                                        i, t)
747 194 storres
        #### Recover Coppersmith information.
748 194 storres
        intIntP = coppersmithTuple[0]
749 194 storres
        N = coppersmithTuple[1]
750 194 storres
        nAtAlpha = N^alpha
751 194 storres
        tBound = coppersmithTuple[2]
752 194 storres
        leastCommonMultiple = coppersmithTuple[3]
753 194 storres
        iBound = max(abs(intLb),abs(intUb))
754 194 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
755 194 storres
        basisConstructionsCount           += 1
756 194 storres
        reductionTime                     = cputime()
757 194 storres
        # Compute the reduced polynomials.
758 194 storres
        ccReducedPolynomialsList =  \
759 212 storres
                slz_compute_coppersmith_reduced_polynomials(intIntP,
760 212 storres
                                                            alpha,
761 212 storres
                                                            N,
762 212 storres
                                                            iBound,
763 212 storres
                                                            tBound)
764 194 storres
        if ccReducedPolynomialsList is None:
765 194 storres
            raise Exception("Reduction failed.")
766 194 storres
        reductionsFullTime    += cputime(reductionTime)
767 194 storres
        reductionsCount       += 1
768 194 storres
        if len(ccReducedPolynomialsList) < 2:
769 194 storres
            print "Nothing to form resultants with."
770 194 storres
            print
771 194 storres
            coppCondFailedCount += 1
772 194 storres
            coppCondFailed = True
773 194 storres
            ##### Apply a different shrink factor according to
774 194 storres
            #  the number of compliant polynomials.
775 194 storres
            if len(ccReducedPolynomialsList) == 0:
776 194 storres
                ub = lb + bw * noCoppersmithIntervalShrink
777 194 storres
            else: # At least one compliant polynomial.
778 194 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
779 194 storres
            if ub > sdub:
780 194 storres
                ub = sdub
781 194 storres
            if lb == ub:
782 194 storres
                raise Exception("Cant shrink interval \
783 194 storres
                anymore to get Coppersmith condition.")
784 194 storres
            nbw = 0
785 194 storres
            continue
786 194 storres
        #### We have at least two polynomials.
787 194 storres
        #    Let us try to compute resultants.
788 194 storres
        resultantsComputationTime      = cputime()
789 194 storres
        resultantsInTTuplesList = []
790 194 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
791 194 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
792 194 storres
                                         len(ccReducedPolynomialsList)):
793 194 storres
                resultantTuple = \
794 194 storres
                slz_resultant_tuple(ccReducedPolynomialsList[polyOuterIndex],
795 194 storres
                                ccReducedPolynomialsList[polyInnerIndex],
796 194 storres
                                t)
797 194 storres
                if len(resultantTuple) > 2:
798 194 storres
                    #print resultantTuple[2]
799 194 storres
                    resultantsInTTuplesList.append(resultantTuple)
800 194 storres
                else:
801 194 storres
                    print "No non nul resultant"
802 194 storres
        print len(resultantsInTTuplesList), "resultant(s) in t tuple(s) created."
803 194 storres
        resultantsComputationsFullTime += cputime(resultantsComputationTime)
804 194 storres
        resultantsComputationsCount    += 1
805 194 storres
        if len(resultantsInTTuplesList) == 0:
806 194 storres
            print "Only null resultants, shrinking interval."
807 194 storres
            resultCondFailed      =  True
808 194 storres
            resultCondFailedCount += 1
809 194 storres
            ### Shrink interval for next iteration.
810 194 storres
            ub = lb + bw * onlyNullResultantsShrink
811 194 storres
            if ub > sdub:
812 194 storres
                ub = sdub
813 194 storres
            nbw = 0
814 194 storres
            continue
815 194 storres
        #### Compute roots.
816 194 storres
        rootsComputationTime       = cputime()
817 194 storres
        reducedPolynomialsRootsSet = set()
818 194 storres
        ##### Solve in the second variable since resultants are in the first
819 194 storres
        #     variable.
820 194 storres
        for resultantInTTuple in resultantsInTTuplesList:
821 194 storres
            currentResultant = resultantInTTuple[2]
822 194 storres
            ##### If the resultant degree is not at least 1, there are no roots.
823 194 storres
            if currentResultant.degree() < 1:
824 194 storres
                print "Resultant is constant:", currentResultant
825 194 storres
                continue # Next resultantInTTuple
826 194 storres
            ##### Compute i roots
827 194 storres
            iRootsList = Zi(currentResultant).roots()
828 194 storres
            ##### For each iRoot, compute the corresponding tRoots and check
829 194 storres
            #     them in the input polynomial.
830 194 storres
            for iRoot in iRootsList:
831 194 storres
                ####### Roots returned by roots() are (value, multiplicity)
832 194 storres
                #       tuples.
833 194 storres
                #print "iRoot:", iRoot
834 194 storres
                ###### Use the tRoot against each polynomial, alternatively.
835 194 storres
                for indexInTuple in range(0,2):
836 194 storres
                    currentPolynomial = resultantInTTuple[indexInTuple]
837 194 storres
                    ####### If the polynomial is univariate, just drop it.
838 194 storres
                    if len(currentPolynomial.variables()) < 2:
839 194 storres
                        print "    Current polynomial is not in two variables."
840 194 storres
                        continue # Next indexInTuple
841 194 storres
                    tRootsList = \
842 194 storres
                        Zt(currentPolynomial.subs({currentPolynomial.variables()[0]:iRoot[0]})).roots()
843 194 storres
                    ####### The tRootsList can be empty, hence the test.
844 194 storres
                    if len(tRootsList) == 0:
845 194 storres
                        print "    No t root."
846 194 storres
                        continue # Next indexInTuple
847 194 storres
                    for tRoot in tRootsList:
848 194 storres
                        reducedPolynomialsRootsSet.add((iRoot[0], tRoot[0]))
849 194 storres
        # End of roots computation
850 194 storres
        rootsComputationsFullTime   =   cputime(rootsComputationTime)
851 194 storres
        rootsComputationsCount      +=  1
852 194 storres
        ##### Prepare for results.
853 194 storres
        intervalResultsList = []
854 194 storres
        intervalResultsList.append((lb, ub))
855 194 storres
        #### Check roots.
856 194 storres
        rootsResultsList = []
857 194 storres
        for root in reducedPolynomialsRootsSet:
858 194 storres
            specificRootResultsList = []
859 194 storres
            failingBounds = []
860 194 storres
            intIntPdivN = intIntP(root[0], root[1]) / N
861 194 storres
            if int(intIntPdivN) != intIntPdivN:
862 194 storres
                continue # Next root
863 194 storres
            # Root qualifies for modular equation, test it for hardness to round.
864 194 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + root[0]) / toIntegerFactor)
865 194 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
866 194 storres
            #print scalingFunction
867 194 storres
            scaledHardToRoundCaseAsFloat = \
868 194 storres
                scalingFunction(hardToRoundCaseAsFloat)
869 194 storres
            print "Candidate HTRNc at x =", \
870 194 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
871 194 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
872 194 storres
                           function,
873 194 storres
                           2^-(targetHardnessToRound),
874 194 storres
                           RRR):
875 194 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
876 194 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
877 194 storres
                    print "Found in interval."
878 194 storres
                else:
879 194 storres
                    print "Found out of interval."
880 194 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
881 194 storres
                # Check the root is in the bounds
882 194 storres
                if abs(root[0]) > iBound or abs(root[1]) > tBound:
883 194 storres
                    print "Root", root, "is out of bounds."
884 194 storres
                    if abs(root[0]) > iBound:
885 194 storres
                        print "root[0]:", root[0]
886 194 storres
                        print "i bound:", iBound
887 194 storres
                        failingBounds.append('i')
888 194 storres
                        failingBounds.append(root[0])
889 194 storres
                        failingBounds.append(iBound)
890 194 storres
                    if abs(root[1]) > tBound:
891 194 storres
                        print "root[1]:", root[1]
892 194 storres
                        print "t bound:", tBound
893 194 storres
                        failingBounds.append('t')
894 194 storres
                        failingBounds.append(root[1])
895 194 storres
                        failingBounds.append(tBound)
896 194 storres
                if len(failingBounds) > 0:
897 194 storres
                    specificRootResultsList.append(failingBounds)
898 194 storres
            else: # From slz_is_htrn...
899 194 storres
                print "is not an HTRN case."
900 194 storres
            if len(specificRootResultsList) > 0:
901 194 storres
                rootsResultsList.append(specificRootResultsList)
902 194 storres
        if len(rootsResultsList) > 0:
903 194 storres
            intervalResultsList.append(rootsResultsList)
904 194 storres
        #### An intervalResultsList has at least the bounds.
905 194 storres
        globalResultsList.append(intervalResultsList)
906 194 storres
        #### Compute an incremented width for next upper bound, only
907 194 storres
        #    if not Coppersmith condition nor resultant condition
908 194 storres
        #    failed at the previous run.
909 194 storres
        if not coppCondFailed and not resultCondFailed:
910 194 storres
            nbw = noErrorIntervalStretch * bw
911 194 storres
        else:
912 194 storres
            nbw = bw
913 194 storres
        ##### Reset the failure flags. They will be raised
914 194 storres
        #     again if needed.
915 194 storres
        coppCondFailed   = False
916 194 storres
        resultCondFailed = False
917 194 storres
        #### For next iteration (at end of loop)
918 194 storres
        #print "nbw:", nbw
919 194 storres
        lb  = ub
920 194 storres
        ub += nbw
921 194 storres
        if ub > sdub:
922 194 storres
            ub = sdub
923 194 storres
        print
924 194 storres
    # End while True
925 194 storres
    ## Main loop just ended.
926 194 storres
    globalWallTime = walltime(wallTimeStart)
927 194 storres
    globalCpuTime  = cputime(cpuTimeStart)
928 194 storres
    ## Output results
929 194 storres
    print ; print "Intervals and HTRNs" ; print
930 194 storres
    for intervalResultsList in globalResultsList:
931 222 storres
        intervalResultString = "[" + str(intervalResultsList[0][0]) +\
932 222 storres
                               "," + str(intervalResultsList[0][1])  + "]"
933 222 storres
        print intervalResultString,
934 194 storres
        if len(intervalResultsList) > 1:
935 194 storres
            rootsResultsList = intervalResultsList[1]
936 222 storres
            specificRootResultIndex = 0
937 194 storres
            for specificRootResultsList in rootsResultsList:
938 222 storres
                if specificRootResultIndex == 0:
939 222 storres
                    print "\t", specificRootResultsList[0],
940 222 storres
                else:
941 222 storres
                    print " " * len(intervalResultString), "\t", \
942 222 storres
                          specificRootResultsList[0],
943 194 storres
                if len(specificRootResultsList) > 1:
944 222 storres
                    print specificRootResultsList[1]
945 222 storres
                specificRootResultIndex += 1
946 194 storres
        print ; print
947 194 storres
    #print globalResultsList
948 194 storres
    #
949 194 storres
    print "Timers and counters"
950 194 storres
    print
951 194 storres
    print "Number of iterations:", iterCount
952 194 storres
    print "Taylor condition failures:", taylCondFailedCount
953 194 storres
    print "Coppersmith condition failures:", coppCondFailedCount
954 194 storres
    print "Resultant condition failures:", resultCondFailedCount
955 194 storres
    print "Iterations count: ", iterCount
956 194 storres
    print "Number of intervals:", len(globalResultsList)
957 194 storres
    print "Number of basis constructions:", basisConstructionsCount
958 194 storres
    print "Total CPU time spent in basis constructions:", \
959 194 storres
        basisConstructionsFullTime
960 194 storres
    if basisConstructionsCount != 0:
961 194 storres
        print "Average basis construction CPU time:", \
962 194 storres
            basisConstructionsFullTime/basisConstructionsCount
963 194 storres
    print "Number of reductions:", reductionsCount
964 194 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
965 194 storres
    if reductionsCount != 0:
966 194 storres
        print "Average reduction CPU time:", \
967 194 storres
            reductionsFullTime/reductionsCount
968 194 storres
    print "Number of resultants computation rounds:", \
969 194 storres
        resultantsComputationsCount
970 194 storres
    print "Total CPU time spent in resultants computation rounds:", \
971 194 storres
        resultantsComputationsFullTime
972 194 storres
    if resultantsComputationsCount != 0:
973 194 storres
        print "Average resultants computation round CPU time:", \
974 194 storres
            resultantsComputationsFullTime/resultantsComputationsCount
975 194 storres
    print "Number of root finding rounds:", rootsComputationsCount
976 194 storres
    print "Total CPU time spent in roots finding rounds:", \
977 194 storres
        rootsComputationsFullTime
978 194 storres
    if rootsComputationsCount != 0:
979 194 storres
        print "Average roots finding round CPU time:", \
980 194 storres
            rootsComputationsFullTime/rootsComputationsCount
981 194 storres
    print "Global Wall time:", globalWallTime
982 194 storres
    print "Global CPU time:", globalCpuTime
983 194 storres
    ## Output counters
984 194 storres
# End srs_runSLZ-v01
985 194 storres
986 194 storres
def srs_run_SLZ_v02(inputFunction,
987 194 storres
                    inputLowerBound,
988 194 storres
                    inputUpperBound,
989 194 storres
                    alpha,
990 194 storres
                    degree,
991 194 storres
                    precision,
992 194 storres
                    emin,
993 194 storres
                    emax,
994 194 storres
                    targetHardnessToRound,
995 194 storres
                    debug = False):
996 194 storres
    """
997 194 storres
    Changes from V1:
998 194 storres
        1- check for roots as soon as a resultant is computed;
999 194 storres
        2- once a non null resultant is found, check for roots;
1000 194 storres
        3- constant resultant == no root.
1001 194 storres
    """
1002 194 storres
1003 194 storres
    if debug:
1004 194 storres
        print "Function                :", inputFunction
1005 194 storres
        print "Lower bound             :", inputLowerBound
1006 194 storres
        print "Upper bounds            :", inputUpperBound
1007 194 storres
        print "Alpha                   :", alpha
1008 194 storres
        print "Degree                  :", degree
1009 194 storres
        print "Precision               :", precision
1010 194 storres
        print "Emin                    :", emin
1011 194 storres
        print "Emax                    :", emax
1012 194 storres
        print "Target hardness-to-round:", targetHardnessToRound
1013 194 storres
        print
1014 194 storres
    ## Important constants.
1015 194 storres
    ### Stretch the interval if no error happens.
1016 194 storres
    noErrorIntervalStretch = 1 + 2^(-5)
1017 194 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
1018 194 storres
    #   by the following factor.
1019 194 storres
    noCoppersmithIntervalShrink = 1/2
1020 194 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
1021 194 storres
    #   shrink the interval by the following factor.
1022 194 storres
    oneCoppersmithIntervalShrink = 3/4
1023 194 storres
    #### If only null resultants are found, shrink the interval by the
1024 194 storres
    #    following factor.
1025 194 storres
    onlyNullResultantsShrink     = 3/4
1026 194 storres
    ## Structures.
1027 194 storres
    RRR         = RealField(precision)
1028 194 storres
    RRIF        = RealIntervalField(precision)
1029 194 storres
    ## Converting input bound into the "right" field.
1030 194 storres
    lowerBound = RRR(inputLowerBound)
1031 194 storres
    upperBound = RRR(inputUpperBound)
1032 194 storres
    ## Before going any further, check domain and image binade conditions.
1033 194 storres
    print inputFunction(1).n()
1034 206 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
1035 206 storres
    if output is None:
1036 206 storres
        print "Invalid domain/image binades. Domain:",\
1037 206 storres
        lowerBound, upperBound, "Images:", \
1038 206 storres
        inputFunction(lowerBound), inputFunction(upperBound)
1039 206 storres
        raise Exception("Invalid domain/image binades.")
1040 206 storres
    lb = output[0] ; ub = output[1]
1041 194 storres
    if lb != lowerBound or ub != upperBound:
1042 194 storres
        print "lb:", lb, " - ub:", ub
1043 194 storres
        print "Invalid domain/image binades. Domain:",\
1044 194 storres
        lowerBound, upperBound, "Images:", \
1045 194 storres
        inputFunction(lowerBound), inputFunction(upperBound)
1046 194 storres
        raise Exception("Invalid domain/image binades.")
1047 194 storres
    #
1048 194 storres
    ## Progam initialization
1049 194 storres
    ### Approximation polynomial accuracy and hardness to round.
1050 194 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
1051 194 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
1052 194 storres
    ### Significand to integer conversion ratio.
1053 194 storres
    toIntegerFactor           = 2^(precision-1)
1054 194 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
1055 194 storres
    ### Variables and rings for polynomials and root searching.
1056 194 storres
    i=var('i')
1057 194 storres
    t=var('t')
1058 194 storres
    inputFunctionVariable = inputFunction.variables()[0]
1059 194 storres
    function = inputFunction.subs({inputFunctionVariable:i})
1060 194 storres
    #  Polynomial Rings over the integers, for root finding.
1061 194 storres
    Zi = ZZ[i]
1062 194 storres
    Zt = ZZ[t]
1063 194 storres
    Zit = ZZ[i,t]
1064 194 storres
    ## Number of iterations limit.
1065 194 storres
    maxIter = 100000
1066 194 storres
    #
1067 194 storres
    ## Compute the scaled function and the degree, in their Sollya version
1068 194 storres
    #  once for all.
1069 194 storres
    (scaledf, sdlb, sdub, silb, siub) = \
1070 194 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
1071 194 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
1072 194 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
1073 194 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
1074 194 storres
    #
1075 194 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
1076 194 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
1077 194 storres
    (unscalingFunction, scalingFunction) = \
1078 194 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
1079 194 storres
    #print scalingFunction, unscalingFunction
1080 194 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
1081 194 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
1082 194 storres
    if internalSollyaPrec < 192:
1083 194 storres
        internalSollyaPrec = 192
1084 194 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
1085 194 storres
    print "Sollya internal precision:", internalSollyaPrec
1086 194 storres
    ## Some variables.
1087 194 storres
    ### General variables
1088 194 storres
    lb                  = sdlb
1089 194 storres
    ub                  = sdub
1090 194 storres
    nbw                 = 0
1091 194 storres
    intervalUlp         = ub.ulp()
1092 194 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
1093 194 storres
    ic                  = 0
1094 194 storres
    icAsInt             = 0    # Set from ic.
1095 194 storres
    solutionsSet        = set()
1096 194 storres
    tsErrorWidth        = []
1097 194 storres
    csErrorVectors      = []
1098 194 storres
    csVectorsResultants = []
1099 194 storres
    floatP              = 0  # Taylor polynomial.
1100 194 storres
    floatPcv            = 0  # Ditto with variable change.
1101 194 storres
    intvl               = "" # Taylor interval
1102 194 storres
    terr                = 0  # Taylor error.
1103 194 storres
    iterCount = 0
1104 194 storres
    htrnSet = set()
1105 194 storres
    ### Timers and counters.
1106 194 storres
    wallTimeStart                   = 0
1107 194 storres
    cpuTimeStart                    = 0
1108 194 storres
    taylCondFailedCount             = 0
1109 194 storres
    coppCondFailedCount             = 0
1110 194 storres
    resultCondFailedCount           = 0
1111 194 storres
    coppCondFailed                  = False
1112 194 storres
    resultCondFailed                = False
1113 194 storres
    globalResultsList               = []
1114 194 storres
    basisConstructionsCount         = 0
1115 194 storres
    basisConstructionsFullTime      = 0
1116 194 storres
    basisConstructionTime           = 0
1117 194 storres
    reductionsCount                 = 0
1118 194 storres
    reductionsFullTime              = 0
1119 194 storres
    reductionTime                   = 0
1120 194 storres
    resultantsComputationsCount     = 0
1121 194 storres
    resultantsComputationsFullTime  = 0
1122 194 storres
    resultantsComputationTime       = 0
1123 194 storres
    rootsComputationsCount          = 0
1124 194 storres
    rootsComputationsFullTime       = 0
1125 194 storres
    rootsComputationTime            = 0
1126 194 storres
    print
1127 194 storres
    ## Global times are started here.
1128 194 storres
    wallTimeStart                   = walltime()
1129 194 storres
    cpuTimeStart                    = cputime()
1130 194 storres
    ## Main loop.
1131 194 storres
    while True:
1132 194 storres
        if lb >= sdub:
1133 194 storres
            print "Lower bound reached upper bound."
1134 194 storres
            break
1135 194 storres
        if iterCount == maxIter:
1136 194 storres
            print "Reached maxIter. Aborting"
1137 194 storres
            break
1138 194 storres
        iterCount += 1
1139 194 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
1140 194 storres
            "log2(numbers)."
1141 194 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
1142 194 storres
        prceSo = slz_compute_polynomial_and_interval(scaledfSo,
1143 194 storres
                                                     degreeSo,
1144 194 storres
                                                     lb,
1145 194 storres
                                                     ub,
1146 194 storres
                                                     polyApproxAccur)
1147 194 storres
        ### Convert back the data into Sage space.
1148 194 storres
        (floatP, floatPcv, intvl, ic, terr) = \
1149 194 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
1150 194 storres
                                                 prceSo[1], prceSo[2],
1151 194 storres
                                                 prceSo[3]))
1152 194 storres
        intvl = RRIF(intvl)
1153 194 storres
        ## Clean-up Sollya stuff.
1154 194 storres
        for elem in prceSo:
1155 194 storres
            sollya_lib_clear_obj(elem)
1156 194 storres
        #print  floatP, floatPcv, intvl, ic, terr
1157 194 storres
        #print floatP
1158 194 storres
        #print intvl.endpoints()[0].n(), \
1159 194 storres
        #      ic.n(),
1160 194 storres
        #intvl.endpoints()[1].n()
1161 194 storres
        ### Check returned data.
1162 194 storres
        #### Is approximation error OK?
1163 194 storres
        if terr > polyApproxAccur:
1164 194 storres
            exceptionErrorMess  = \
1165 194 storres
                "Approximation failed - computed error:" + \
1166 194 storres
                str(terr) + " - target error: "
1167 194 storres
            exceptionErrorMess += \
1168 194 storres
                str(polyApproxAccur) + ". Aborting!"
1169 194 storres
            raise Exception(exceptionErrorMess)
1170 194 storres
        #### Is lower bound OK?
1171 194 storres
        if lb != intvl.endpoints()[0]:
1172 194 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
1173 194 storres
                               str(lb) + ". Aborting!"
1174 194 storres
            raise Exception(exceptionErrorMess)
1175 194 storres
        #### Set upper bound.
1176 194 storres
        if ub > intvl.endpoints()[1]:
1177 194 storres
            ub = intvl.endpoints()[1]
1178 194 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
1179 194 storres
            "log2(numbers)."
1180 194 storres
            taylCondFailedCount += 1
1181 194 storres
        #### Is interval not degenerate?
1182 194 storres
        if lb >= ub:
1183 194 storres
            exceptionErrorMess = "Degenerate interval: " + \
1184 194 storres
                                "lowerBound(" + str(lb) +\
1185 194 storres
                                ")>= upperBound(" + str(ub) + \
1186 194 storres
                                "). Aborting!"
1187 194 storres
            raise Exception(exceptionErrorMess)
1188 194 storres
        #### Is interval center ok?
1189 194 storres
        if ic <= lb or ic >= ub:
1190 194 storres
            exceptionErrorMess =  "Invalid interval center for " + \
1191 194 storres
                                str(lb) + ',' + str(ic) + ',' +  \
1192 194 storres
                                str(ub) + ". Aborting!"
1193 194 storres
            raise Exception(exceptionErrorMess)
1194 194 storres
        ##### Current interval width and reset future interval width.
1195 194 storres
        bw = ub - lb
1196 194 storres
        nbw = 0
1197 194 storres
        icAsInt = int(ic * toIntegerFactor)
1198 194 storres
        #### The following ratio is always >= 1. In case we may want to
1199 197 storres
        #    enlarge the interval
1200 194 storres
        curTaylErrRat = polyApproxAccur / terr
1201 197 storres
        ### Make the  integral transformations.
1202 197 storres
        #### Bounds and interval center.
1203 194 storres
        intIc = int(ic * toIntegerFactor)
1204 194 storres
        intLb = int(lb * toIntegerFactor) - intIc
1205 194 storres
        intUb = int(ub * toIntegerFactor) - intIc
1206 194 storres
        #
1207 197 storres
        #### Polynomials
1208 194 storres
        basisConstructionTime         = cputime()
1209 194 storres
        ##### To a polynomial with rational coefficients with rational arguments
1210 194 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
1211 194 storres
        ##### To a polynomial with rational coefficients with integer arguments
1212 194 storres
        ratIntP = \
1213 194 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
1214 197 storres
        #####  Ultimately a multivariate polynomial with integer coefficients
1215 197 storres
        #      with integer arguments.
1216 194 storres
        coppersmithTuple = \
1217 194 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
1218 194 storres
                                                        precision,
1219 194 storres
                                                        targetHardnessToRound,
1220 194 storres
                                                        i, t)
1221 194 storres
        #### Recover Coppersmith information.
1222 194 storres
        intIntP = coppersmithTuple[0]
1223 194 storres
        N = coppersmithTuple[1]
1224 194 storres
        nAtAlpha = N^alpha
1225 194 storres
        tBound = coppersmithTuple[2]
1226 194 storres
        leastCommonMultiple = coppersmithTuple[3]
1227 194 storres
        iBound = max(abs(intLb),abs(intUb))
1228 194 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
1229 194 storres
        basisConstructionsCount           += 1
1230 194 storres
        reductionTime                     = cputime()
1231 197 storres
        #### Compute the reduced polynomials.
1232 194 storres
        ccReducedPolynomialsList =  \
1233 212 storres
                slz_compute_coppersmith_reduced_polynomials(intIntP,
1234 212 storres
                                                            alpha,
1235 212 storres
                                                            N,
1236 212 storres
                                                            iBound,
1237 212 storres
                                                            tBound)
1238 194 storres
        if ccReducedPolynomialsList is None:
1239 194 storres
            raise Exception("Reduction failed.")
1240 194 storres
        reductionsFullTime    += cputime(reductionTime)
1241 194 storres
        reductionsCount       += 1
1242 194 storres
        if len(ccReducedPolynomialsList) < 2:
1243 194 storres
            print "Nothing to form resultants with."
1244 194 storres
            print
1245 194 storres
            coppCondFailedCount += 1
1246 194 storres
            coppCondFailed = True
1247 194 storres
            ##### Apply a different shrink factor according to
1248 194 storres
            #  the number of compliant polynomials.
1249 194 storres
            if len(ccReducedPolynomialsList) == 0:
1250 194 storres
                ub = lb + bw * noCoppersmithIntervalShrink
1251 194 storres
            else: # At least one compliant polynomial.
1252 194 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
1253 194 storres
            if ub > sdub:
1254 194 storres
                ub = sdub
1255 194 storres
            if lb == ub:
1256 194 storres
                raise Exception("Cant shrink interval \
1257 194 storres
                anymore to get Coppersmith condition.")
1258 194 storres
            nbw = 0
1259 194 storres
            continue
1260 194 storres
        #### We have at least two polynomials.
1261 194 storres
        #    Let us try to compute resultants.
1262 194 storres
        #    For each resultant computed, go for the solutions.
1263 194 storres
        ##### Build the pairs list.
1264 194 storres
        polyPairsList           = []
1265 194 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
1266 194 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
1267 194 storres
                                         len(ccReducedPolynomialsList)):
1268 194 storres
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
1269 194 storres
                                      ccReducedPolynomialsList[polyInnerIndex]))
1270 197 storres
        #### Actual root search.
1271 197 storres
        rootsSet            = set()
1272 197 storres
        hasNonNullResultant = False
1273 194 storres
        for polyPair in polyPairsList:
1274 197 storres
            if hasNonNullResultant:
1275 197 storres
                break
1276 197 storres
            resultantsComputationTime   = cputime()
1277 197 storres
            currentResultant = \
1278 197 storres
                slz_resultant(polyPair[0],
1279 197 storres
                              polyPair[1],
1280 197 storres
                              t)
1281 194 storres
            resultantsComputationsFullTime += cputime(resultantsComputationTime)
1282 194 storres
            resultantsComputationsCount    += 1
1283 197 storres
            if currentResultant is None:
1284 197 storres
                print "Nul resultant"
1285 197 storres
                continue # Next polyPair.
1286 197 storres
            else:
1287 194 storres
                hasNonNullResultant = True
1288 197 storres
            #### We have a non null resultant. From now on, whatever the
1289 197 storres
            #    root search yields, no extra root search is necessary.
1290 197 storres
            #### A constant resultant leads to no root. Root search is done.
1291 194 storres
            if currentResultant.degree() < 1:
1292 194 storres
                print "Resultant is constant:", currentResultant
1293 197 storres
                continue # Next polyPair and should break.
1294 197 storres
            #### Actual roots computation.
1295 197 storres
            rootsComputationTime       = cputime()
1296 194 storres
            ##### Compute i roots
1297 194 storres
            iRootsList = Zi(currentResultant).roots()
1298 197 storres
            ##### For each iRoot, compute the corresponding tRoots and
1299 197 storres
            #     and build populate the .rootsSet.
1300 194 storres
            for iRoot in iRootsList:
1301 194 storres
                ####### Roots returned by roots() are (value, multiplicity)
1302 194 storres
                #       tuples.
1303 194 storres
                #print "iRoot:", iRoot
1304 194 storres
                ###### Use the tRoot against each polynomial, alternatively.
1305 197 storres
                for indexInPair in range(0,2):
1306 197 storres
                    currentPolynomial = polyPair[indexInPair]
1307 194 storres
                    ####### If the polynomial is univariate, just drop it.
1308 194 storres
                    if len(currentPolynomial.variables()) < 2:
1309 194 storres
                        print "    Current polynomial is not in two variables."
1310 197 storres
                        continue # Next indexInPair
1311 194 storres
                    tRootsList = \
1312 194 storres
                        Zt(currentPolynomial.subs({currentPolynomial.variables()[0]:iRoot[0]})).roots()
1313 194 storres
                    ####### The tRootsList can be empty, hence the test.
1314 194 storres
                    if len(tRootsList) == 0:
1315 194 storres
                        print "    No t root."
1316 197 storres
                        continue # Next indexInPair
1317 194 storres
                    for tRoot in tRootsList:
1318 197 storres
                        rootsSet.add((iRoot[0], tRoot[0]))
1319 197 storres
            # End of roots computation.
1320 197 storres
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
1321 197 storres
            rootsComputationsCount      +=  1
1322 197 storres
        # End loop for polyPair in polyParsList.  Will break at next iteration.
1323 197 storres
        # since a non null resultant was found.
1324 197 storres
        #### Prepare for results for the current interval..
1325 194 storres
        intervalResultsList = []
1326 194 storres
        intervalResultsList.append((lb, ub))
1327 194 storres
        #### Check roots.
1328 194 storres
        rootsResultsList = []
1329 197 storres
        for root in rootsSet:
1330 194 storres
            specificRootResultsList = []
1331 194 storres
            failingBounds = []
1332 194 storres
            intIntPdivN = intIntP(root[0], root[1]) / N
1333 194 storres
            if int(intIntPdivN) != intIntPdivN:
1334 194 storres
                continue # Next root
1335 194 storres
            # Root qualifies for modular equation, test it for hardness to round.
1336 194 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + root[0]) / toIntegerFactor)
1337 194 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
1338 194 storres
            #print scalingFunction
1339 194 storres
            scaledHardToRoundCaseAsFloat = \
1340 194 storres
                scalingFunction(hardToRoundCaseAsFloat)
1341 194 storres
            print "Candidate HTRNc at x =", \
1342 194 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
1343 194 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
1344 194 storres
                           function,
1345 194 storres
                           2^-(targetHardnessToRound),
1346 194 storres
                           RRR):
1347 194 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
1348 194 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
1349 194 storres
                    print "Found in interval."
1350 194 storres
                else:
1351 194 storres
                    print "Found out of interval."
1352 194 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
1353 194 storres
                # Check the root is in the bounds
1354 194 storres
                if abs(root[0]) > iBound or abs(root[1]) > tBound:
1355 197 storres
                    print "Root", root, "is out of bounds for modular equation."
1356 194 storres
                    if abs(root[0]) > iBound:
1357 194 storres
                        print "root[0]:", root[0]
1358 194 storres
                        print "i bound:", iBound
1359 194 storres
                        failingBounds.append('i')
1360 194 storres
                        failingBounds.append(root[0])
1361 194 storres
                        failingBounds.append(iBound)
1362 194 storres
                    if abs(root[1]) > tBound:
1363 194 storres
                        print "root[1]:", root[1]
1364 194 storres
                        print "t bound:", tBound
1365 194 storres
                        failingBounds.append('t')
1366 194 storres
                        failingBounds.append(root[1])
1367 194 storres
                        failingBounds.append(tBound)
1368 194 storres
                if len(failingBounds) > 0:
1369 194 storres
                    specificRootResultsList.append(failingBounds)
1370 194 storres
            else: # From slz_is_htrn...
1371 194 storres
                print "is not an HTRN case."
1372 194 storres
            if len(specificRootResultsList) > 0:
1373 194 storres
                rootsResultsList.append(specificRootResultsList)
1374 194 storres
        if len(rootsResultsList) > 0:
1375 194 storres
            intervalResultsList.append(rootsResultsList)
1376 197 storres
        ### Check if a non null resultant was found. If not shrink the interval.
1377 197 storres
        if not hasNonNullResultant:
1378 197 storres
            print "Only null resultants for this reduction, shrinking interval."
1379 197 storres
            resultCondFailed      =  True
1380 197 storres
            resultCondFailedCount += 1
1381 197 storres
            ### Shrink interval for next iteration.
1382 197 storres
            ub = lb + bw * onlyNullResultantsShrink
1383 197 storres
            if ub > sdub:
1384 197 storres
                ub = sdub
1385 197 storres
            nbw = 0
1386 197 storres
            continue
1387 194 storres
        #### An intervalResultsList has at least the bounds.
1388 194 storres
        globalResultsList.append(intervalResultsList)
1389 194 storres
        #### Compute an incremented width for next upper bound, only
1390 194 storres
        #    if not Coppersmith condition nor resultant condition
1391 194 storres
        #    failed at the previous run.
1392 194 storres
        if not coppCondFailed and not resultCondFailed:
1393 194 storres
            nbw = noErrorIntervalStretch * bw
1394 194 storres
        else:
1395 194 storres
            nbw = bw
1396 194 storres
        ##### Reset the failure flags. They will be raised
1397 194 storres
        #     again if needed.
1398 194 storres
        coppCondFailed   = False
1399 194 storres
        resultCondFailed = False
1400 194 storres
        #### For next iteration (at end of loop)
1401 194 storres
        #print "nbw:", nbw
1402 194 storres
        lb  = ub
1403 194 storres
        ub += nbw
1404 194 storres
        if ub > sdub:
1405 194 storres
            ub = sdub
1406 194 storres
        print
1407 194 storres
    # End while True
1408 194 storres
    ## Main loop just ended.
1409 194 storres
    globalWallTime = walltime(wallTimeStart)
1410 194 storres
    globalCpuTime  = cputime(cpuTimeStart)
1411 194 storres
    ## Output results
1412 194 storres
    print ; print "Intervals and HTRNs" ; print
1413 194 storres
    for intervalResultsList in globalResultsList:
1414 222 storres
        intervalResultString = "[" + str(intervalResultsList[0][0]) +\
1415 222 storres
                               "," + str(intervalResultsList[0][1])  + "]"
1416 222 storres
        print intervalResultString,
1417 194 storres
        if len(intervalResultsList) > 1:
1418 194 storres
            rootsResultsList = intervalResultsList[1]
1419 222 storres
            specificRootResultIndex = 0
1420 194 storres
            for specificRootResultsList in rootsResultsList:
1421 222 storres
                if specificRootResultIndex == 0:
1422 222 storres
                    print "\t", specificRootResultsList[0],
1423 222 storres
                else:
1424 222 storres
                    print " " * len(intervalResultString), "\t", \
1425 222 storres
                          specificRootResultsList[0],
1426 194 storres
                if len(specificRootResultsList) > 1:
1427 222 storres
                    print specificRootResultsList[1]
1428 222 storres
                specificRootResultIndex += 1
1429 194 storres
        print ; print
1430 194 storres
    #print globalResultsList
1431 194 storres
    #
1432 194 storres
    print "Timers and counters"
1433 194 storres
    print
1434 194 storres
    print "Number of iterations:", iterCount
1435 194 storres
    print "Taylor condition failures:", taylCondFailedCount
1436 194 storres
    print "Coppersmith condition failures:", coppCondFailedCount
1437 194 storres
    print "Resultant condition failures:", resultCondFailedCount
1438 194 storres
    print "Iterations count: ", iterCount
1439 194 storres
    print "Number of intervals:", len(globalResultsList)
1440 194 storres
    print "Number of basis constructions:", basisConstructionsCount
1441 194 storres
    print "Total CPU time spent in basis constructions:", \
1442 194 storres
        basisConstructionsFullTime
1443 194 storres
    if basisConstructionsCount != 0:
1444 194 storres
        print "Average basis construction CPU time:", \
1445 194 storres
            basisConstructionsFullTime/basisConstructionsCount
1446 194 storres
    print "Number of reductions:", reductionsCount
1447 194 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
1448 194 storres
    if reductionsCount != 0:
1449 194 storres
        print "Average reduction CPU time:", \
1450 194 storres
            reductionsFullTime/reductionsCount
1451 194 storres
    print "Number of resultants computation rounds:", \
1452 194 storres
        resultantsComputationsCount
1453 194 storres
    print "Total CPU time spent in resultants computation rounds:", \
1454 194 storres
        resultantsComputationsFullTime
1455 194 storres
    if resultantsComputationsCount != 0:
1456 194 storres
        print "Average resultants computation round CPU time:", \
1457 194 storres
            resultantsComputationsFullTime/resultantsComputationsCount
1458 194 storres
    print "Number of root finding rounds:", rootsComputationsCount
1459 194 storres
    print "Total CPU time spent in roots finding rounds:", \
1460 194 storres
        rootsComputationsFullTime
1461 194 storres
    if rootsComputationsCount != 0:
1462 194 storres
        print "Average roots finding round CPU time:", \
1463 194 storres
            rootsComputationsFullTime/rootsComputationsCount
1464 194 storres
    print "Global Wall time:", globalWallTime
1465 194 storres
    print "Global CPU time:", globalCpuTime
1466 194 storres
    ## Output counters
1467 194 storres
# End srs_runSLZ-v02
1468 194 storres
1469 212 storres
def srs_run_SLZ_v03(inputFunction,
1470 212 storres
                    inputLowerBound,
1471 212 storres
                    inputUpperBound,
1472 212 storres
                    alpha,
1473 212 storres
                    degree,
1474 212 storres
                    precision,
1475 212 storres
                    emin,
1476 212 storres
                    emax,
1477 212 storres
                    targetHardnessToRound,
1478 212 storres
                    debug = False):
1479 212 storres
    """
1480 212 storres
    Changes from V2:
1481 212 storres
        Root search is changed:
1482 212 storres
            - we compute the resultants in i and in t;
1483 212 storres
            - we compute the roots set of each of these resultants;
1484 212 storres
            - we combine all the possible pairs between the two sets;
1485 212 storres
            - we check these pairs in polynomials for correctness.
1486 212 storres
    Changes from V1:
1487 212 storres
        1- check for roots as soon as a resultant is computed;
1488 212 storres
        2- once a non null resultant is found, check for roots;
1489 212 storres
        3- constant resultant == no root.
1490 212 storres
    """
1491 212 storres
1492 212 storres
    if debug:
1493 212 storres
        print "Function                :", inputFunction
1494 212 storres
        print "Lower bound             :", inputLowerBound
1495 212 storres
        print "Upper bounds            :", inputUpperBound
1496 212 storres
        print "Alpha                   :", alpha
1497 212 storres
        print "Degree                  :", degree
1498 212 storres
        print "Precision               :", precision
1499 212 storres
        print "Emin                    :", emin
1500 212 storres
        print "Emax                    :", emax
1501 212 storres
        print "Target hardness-to-round:", targetHardnessToRound
1502 212 storres
        print
1503 212 storres
    ## Important constants.
1504 212 storres
    ### Stretch the interval if no error happens.
1505 212 storres
    noErrorIntervalStretch = 1 + 2^(-5)
1506 212 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
1507 212 storres
    #   by the following factor.
1508 212 storres
    noCoppersmithIntervalShrink = 1/2
1509 212 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
1510 212 storres
    #   shrink the interval by the following factor.
1511 212 storres
    oneCoppersmithIntervalShrink = 3/4
1512 212 storres
    #### If only null resultants are found, shrink the interval by the
1513 212 storres
    #    following factor.
1514 212 storres
    onlyNullResultantsShrink     = 3/4
1515 212 storres
    ## Structures.
1516 212 storres
    RRR         = RealField(precision)
1517 212 storres
    RRIF        = RealIntervalField(precision)
1518 212 storres
    ## Converting input bound into the "right" field.
1519 212 storres
    lowerBound = RRR(inputLowerBound)
1520 212 storres
    upperBound = RRR(inputUpperBound)
1521 212 storres
    ## Before going any further, check domain and image binade conditions.
1522 212 storres
    print inputFunction(1).n()
1523 212 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
1524 212 storres
    if output is None:
1525 212 storres
        print "Invalid domain/image binades. Domain:",\
1526 212 storres
        lowerBound, upperBound, "Images:", \
1527 212 storres
        inputFunction(lowerBound), inputFunction(upperBound)
1528 212 storres
        raise Exception("Invalid domain/image binades.")
1529 212 storres
    lb = output[0] ; ub = output[1]
1530 212 storres
    if lb != lowerBound or ub != upperBound:
1531 212 storres
        print "lb:", lb, " - ub:", ub
1532 212 storres
        print "Invalid domain/image binades. Domain:",\
1533 212 storres
        lowerBound, upperBound, "Images:", \
1534 212 storres
        inputFunction(lowerBound), inputFunction(upperBound)
1535 212 storres
        raise Exception("Invalid domain/image binades.")
1536 212 storres
    #
1537 212 storres
    ## Progam initialization
1538 212 storres
    ### Approximation polynomial accuracy and hardness to round.
1539 212 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
1540 212 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
1541 212 storres
    ### Significand to integer conversion ratio.
1542 212 storres
    toIntegerFactor           = 2^(precision-1)
1543 212 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
1544 212 storres
    ### Variables and rings for polynomials and root searching.
1545 212 storres
    i=var('i')
1546 212 storres
    t=var('t')
1547 212 storres
    inputFunctionVariable = inputFunction.variables()[0]
1548 212 storres
    function = inputFunction.subs({inputFunctionVariable:i})
1549 212 storres
    #  Polynomial Rings over the integers, for root finding.
1550 212 storres
    Zi = ZZ[i]
1551 212 storres
    Zt = ZZ[t]
1552 212 storres
    Zit = ZZ[i,t]
1553 212 storres
    ## Number of iterations limit.
1554 212 storres
    maxIter = 100000
1555 212 storres
    #
1556 212 storres
    ## Compute the scaled function and the degree, in their Sollya version
1557 212 storres
    #  once for all.
1558 212 storres
    (scaledf, sdlb, sdub, silb, siub) = \
1559 212 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
1560 212 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
1561 212 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
1562 212 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
1563 212 storres
    #
1564 212 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
1565 212 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
1566 212 storres
    (unscalingFunction, scalingFunction) = \
1567 212 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
1568 212 storres
    #print scalingFunction, unscalingFunction
1569 212 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
1570 212 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
1571 212 storres
    if internalSollyaPrec < 192:
1572 212 storres
        internalSollyaPrec = 192
1573 212 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
1574 212 storres
    print "Sollya internal precision:", internalSollyaPrec
1575 212 storres
    ## Some variables.
1576 212 storres
    ### General variables
1577 212 storres
    lb                  = sdlb
1578 212 storres
    ub                  = sdub
1579 212 storres
    nbw                 = 0
1580 212 storres
    intervalUlp         = ub.ulp()
1581 212 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
1582 212 storres
    ic                  = 0
1583 212 storres
    icAsInt             = 0    # Set from ic.
1584 212 storres
    solutionsSet        = set()
1585 212 storres
    tsErrorWidth        = []
1586 212 storres
    csErrorVectors      = []
1587 212 storres
    csVectorsResultants = []
1588 212 storres
    floatP              = 0  # Taylor polynomial.
1589 212 storres
    floatPcv            = 0  # Ditto with variable change.
1590 212 storres
    intvl               = "" # Taylor interval
1591 212 storres
    terr                = 0  # Taylor error.
1592 212 storres
    iterCount = 0
1593 212 storres
    htrnSet = set()
1594 212 storres
    ### Timers and counters.
1595 212 storres
    wallTimeStart                   = 0
1596 212 storres
    cpuTimeStart                    = 0
1597 212 storres
    taylCondFailedCount             = 0
1598 212 storres
    coppCondFailedCount             = 0
1599 212 storres
    resultCondFailedCount           = 0
1600 212 storres
    coppCondFailed                  = False
1601 212 storres
    resultCondFailed                = False
1602 212 storres
    globalResultsList               = []
1603 212 storres
    basisConstructionsCount         = 0
1604 212 storres
    basisConstructionsFullTime      = 0
1605 212 storres
    basisConstructionTime           = 0
1606 212 storres
    reductionsCount                 = 0
1607 212 storres
    reductionsFullTime              = 0
1608 212 storres
    reductionTime                   = 0
1609 212 storres
    resultantsComputationsCount     = 0
1610 212 storres
    resultantsComputationsFullTime  = 0
1611 212 storres
    resultantsComputationTime       = 0
1612 212 storres
    rootsComputationsCount          = 0
1613 212 storres
    rootsComputationsFullTime       = 0
1614 212 storres
    rootsComputationTime            = 0
1615 212 storres
    print
1616 212 storres
    ## Global times are started here.
1617 212 storres
    wallTimeStart                   = walltime()
1618 212 storres
    cpuTimeStart                    = cputime()
1619 212 storres
    ## Main loop.
1620 212 storres
    while True:
1621 212 storres
        if lb >= sdub:
1622 212 storres
            print "Lower bound reached upper bound."
1623 212 storres
            break
1624 212 storres
        if iterCount == maxIter:
1625 212 storres
            print "Reached maxIter. Aborting"
1626 212 storres
            break
1627 212 storres
        iterCount += 1
1628 212 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
1629 212 storres
            "log2(numbers)."
1630 212 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
1631 212 storres
        prceSo = slz_compute_polynomial_and_interval(scaledfSo,
1632 212 storres
                                                     degreeSo,
1633 212 storres
                                                     lb,
1634 212 storres
                                                     ub,
1635 212 storres
                                                     polyApproxAccur)
1636 212 storres
        ### Convert back the data into Sage space.
1637 212 storres
        (floatP, floatPcv, intvl, ic, terr) = \
1638 212 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
1639 212 storres
                                                 prceSo[1], prceSo[2],
1640 212 storres
                                                 prceSo[3]))
1641 212 storres
        intvl = RRIF(intvl)
1642 212 storres
        ## Clean-up Sollya stuff.
1643 212 storres
        for elem in prceSo:
1644 212 storres
            sollya_lib_clear_obj(elem)
1645 212 storres
        #print  floatP, floatPcv, intvl, ic, terr
1646 212 storres
        #print floatP
1647 212 storres
        #print intvl.endpoints()[0].n(), \
1648 212 storres
        #      ic.n(),
1649 212 storres
        #intvl.endpoints()[1].n()
1650 212 storres
        ### Check returned data.
1651 212 storres
        #### Is approximation error OK?
1652 212 storres
        if terr > polyApproxAccur:
1653 212 storres
            exceptionErrorMess  = \
1654 212 storres
                "Approximation failed - computed error:" + \
1655 212 storres
                str(terr) + " - target error: "
1656 212 storres
            exceptionErrorMess += \
1657 212 storres
                str(polyApproxAccur) + ". Aborting!"
1658 212 storres
            raise Exception(exceptionErrorMess)
1659 212 storres
        #### Is lower bound OK?
1660 212 storres
        if lb != intvl.endpoints()[0]:
1661 212 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
1662 212 storres
                               str(lb) + ". Aborting!"
1663 212 storres
            raise Exception(exceptionErrorMess)
1664 212 storres
        #### Set upper bound.
1665 212 storres
        if ub > intvl.endpoints()[1]:
1666 212 storres
            ub = intvl.endpoints()[1]
1667 212 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
1668 212 storres
            "log2(numbers)."
1669 212 storres
            taylCondFailedCount += 1
1670 212 storres
        #### Is interval not degenerate?
1671 212 storres
        if lb >= ub:
1672 212 storres
            exceptionErrorMess = "Degenerate interval: " + \
1673 212 storres
                                "lowerBound(" + str(lb) +\
1674 212 storres
                                ")>= upperBound(" + str(ub) + \
1675 212 storres
                                "). Aborting!"
1676 212 storres
            raise Exception(exceptionErrorMess)
1677 212 storres
        #### Is interval center ok?
1678 212 storres
        if ic <= lb or ic >= ub:
1679 212 storres
            exceptionErrorMess =  "Invalid interval center for " + \
1680 212 storres
                                str(lb) + ',' + str(ic) + ',' +  \
1681 212 storres
                                str(ub) + ". Aborting!"
1682 212 storres
            raise Exception(exceptionErrorMess)
1683 212 storres
        ##### Current interval width and reset future interval width.
1684 212 storres
        bw = ub - lb
1685 212 storres
        nbw = 0
1686 212 storres
        icAsInt = int(ic * toIntegerFactor)
1687 212 storres
        #### The following ratio is always >= 1. In case we may want to
1688 212 storres
        #    enlarge the interval
1689 212 storres
        curTaylErrRat = polyApproxAccur / terr
1690 212 storres
        ### Make the  integral transformations.
1691 212 storres
        #### Bounds and interval center.
1692 212 storres
        intIc = int(ic * toIntegerFactor)
1693 212 storres
        intLb = int(lb * toIntegerFactor) - intIc
1694 212 storres
        intUb = int(ub * toIntegerFactor) - intIc
1695 212 storres
        #
1696 212 storres
        #### Polynomials
1697 212 storres
        basisConstructionTime         = cputime()
1698 212 storres
        ##### To a polynomial with rational coefficients with rational arguments
1699 212 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
1700 212 storres
        ##### To a polynomial with rational coefficients with integer arguments
1701 212 storres
        ratIntP = \
1702 212 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
1703 212 storres
        #####  Ultimately a multivariate polynomial with integer coefficients
1704 212 storres
        #      with integer arguments.
1705 212 storres
        coppersmithTuple = \
1706 212 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
1707 212 storres
                                                        precision,
1708 212 storres
                                                        targetHardnessToRound,
1709 212 storres
                                                        i, t)
1710 212 storres
        #### Recover Coppersmith information.
1711 212 storres
        intIntP = coppersmithTuple[0]
1712 212 storres
        N = coppersmithTuple[1]
1713 212 storres
        nAtAlpha = N^alpha
1714 212 storres
        tBound = coppersmithTuple[2]
1715 212 storres
        leastCommonMultiple = coppersmithTuple[3]
1716 212 storres
        iBound = max(abs(intLb),abs(intUb))
1717 212 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
1718 212 storres
        basisConstructionsCount           += 1
1719 212 storres
        reductionTime                     = cputime()
1720 212 storres
        #### Compute the reduced polynomials.
1721 212 storres
        ccReducedPolynomialsList =  \
1722 212 storres
                slz_compute_coppersmith_reduced_polynomials(intIntP,
1723 212 storres
                                                            alpha,
1724 212 storres
                                                            N,
1725 212 storres
                                                            iBound,
1726 212 storres
                                                            tBound)
1727 212 storres
        if ccReducedPolynomialsList is None:
1728 212 storres
            raise Exception("Reduction failed.")
1729 212 storres
        reductionsFullTime    += cputime(reductionTime)
1730 212 storres
        reductionsCount       += 1
1731 212 storres
        if len(ccReducedPolynomialsList) < 2:
1732 212 storres
            print "Nothing to form resultants with."
1733 212 storres
            print
1734 212 storres
            coppCondFailedCount += 1
1735 212 storres
            coppCondFailed = True
1736 212 storres
            ##### Apply a different shrink factor according to
1737 212 storres
            #  the number of compliant polynomials.
1738 212 storres
            if len(ccReducedPolynomialsList) == 0:
1739 212 storres
                ub = lb + bw * noCoppersmithIntervalShrink
1740 212 storres
            else: # At least one compliant polynomial.
1741 212 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
1742 212 storres
            if ub > sdub:
1743 212 storres
                ub = sdub
1744 212 storres
            if lb == ub:
1745 212 storres
                raise Exception("Cant shrink interval \
1746 212 storres
                anymore to get Coppersmith condition.")
1747 212 storres
            nbw = 0
1748 212 storres
            continue
1749 212 storres
        #### We have at least two polynomials.
1750 212 storres
        #    Let us try to compute resultants.
1751 212 storres
        #    For each resultant computed, go for the solutions.
1752 212 storres
        ##### Build the pairs list.
1753 212 storres
        polyPairsList           = []
1754 212 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
1755 212 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
1756 212 storres
                                         len(ccReducedPolynomialsList)):
1757 212 storres
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
1758 212 storres
                                      ccReducedPolynomialsList[polyInnerIndex]))
1759 212 storres
        #### Actual root search.
1760 212 storres
        rootsSet            = set()
1761 212 storres
        hasNonNullResultant = False
1762 212 storres
        for polyPair in polyPairsList:
1763 212 storres
            if hasNonNullResultant:
1764 212 storres
                break
1765 212 storres
            resultantsComputationTime   = cputime()
1766 212 storres
            currentResultantI = \
1767 212 storres
                slz_resultant(polyPair[0],
1768 212 storres
                              polyPair[1],
1769 212 storres
                              t)
1770 212 storres
            resultantsComputationsCount    += 1
1771 212 storres
            if currentResultantI is None:
1772 212 storres
                resultantsComputationsFullTime +=  \
1773 212 storres
                    cputime(resultantsComputationTime)
1774 212 storres
                print "Nul resultant"
1775 212 storres
                continue # Next polyPair.
1776 212 storres
            currentResultantT = \
1777 212 storres
                slz_resultant(polyPair[0],
1778 212 storres
                              polyPair[1],
1779 212 storres
                              i)
1780 212 storres
            resultantsComputationsFullTime += cputime(resultantsComputationTime)
1781 212 storres
            resultantsComputationsCount    += 1
1782 212 storres
            if currentResultantT is None:
1783 212 storres
                print "Nul resultant"
1784 212 storres
                continue # Next polyPair.
1785 212 storres
            else:
1786 212 storres
                hasNonNullResultant = True
1787 212 storres
            #### We have a non null resultants pair. From now on, whatever the
1788 212 storres
            #    root search yields, no extra root search is necessary.
1789 212 storres
            #### A constant resultant leads to no root. Root search is done.
1790 212 storres
            if currentResultantI.degree() < 1:
1791 212 storres
                print "Resultant is constant:", currentResultantI
1792 212 storres
                break # Next polyPair and should break.
1793 212 storres
            if currentResultantT.degree() < 1:
1794 212 storres
                print "Resultant is constant:", currentResultantT
1795 212 storres
                break # Next polyPair and should break.
1796 212 storres
            #### Actual roots computation.
1797 212 storres
            rootsComputationTime       = cputime()
1798 212 storres
            ##### Compute i roots
1799 212 storres
            iRootsList = Zi(currentResultantI).roots()
1800 212 storres
            rootsComputationsCount      +=  1
1801 212 storres
            if len(iRootsList) == 0:
1802 212 storres
                rootsComputationsFullTime   =   cputime(rootsComputationTime)
1803 212 storres
                print "No roots in \"i\"."
1804 212 storres
                break # No roots in i.
1805 212 storres
            tRootsList = Zt(currentResultantT).roots()
1806 212 storres
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
1807 212 storres
            rootsComputationsCount      +=  1
1808 212 storres
            if len(tRootsList) == 0:
1809 212 storres
                print "No roots in \"t\"."
1810 212 storres
                break # No roots in i.
1811 212 storres
            ##### For each iRoot, get a tRoot and check against the polynomials.
1812 212 storres
            for iRoot in iRootsList:
1813 212 storres
                ####### Roots returned by roots() are (value, multiplicity)
1814 212 storres
                #       tuples.
1815 212 storres
                #print "iRoot:", iRoot
1816 212 storres
                for tRoot in tRootsList:
1817 212 storres
                ###### Use the tRoot against each polynomial, alternatively.
1818 212 storres
                    if polyPair[0](iRoot[0],tRoot[0]) != 0:
1819 212 storres
                        continue
1820 212 storres
                    if polyPair[1](iRoot[0],tRoot[0]) != 0:
1821 212 storres
                        continue
1822 212 storres
                    rootsSet.add((iRoot[0], tRoot[0]))
1823 212 storres
            # End of roots computation.
1824 212 storres
        # End loop for polyPair in polyParsList.  Will break at next iteration.
1825 212 storres
        # since a non null resultant was found.
1826 212 storres
        #### Prepare for results for the current interval..
1827 212 storres
        intervalResultsList = []
1828 212 storres
        intervalResultsList.append((lb, ub))
1829 212 storres
        #### Check roots.
1830 212 storres
        rootsResultsList = []
1831 212 storres
        for root in rootsSet:
1832 212 storres
            specificRootResultsList = []
1833 212 storres
            failingBounds = []
1834 212 storres
            intIntPdivN = intIntP(root[0], root[1]) / N
1835 212 storres
            if int(intIntPdivN) != intIntPdivN:
1836 212 storres
                continue # Next root
1837 212 storres
            # Root qualifies for modular equation, test it for hardness to round.
1838 212 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + root[0]) / toIntegerFactor)
1839 212 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
1840 212 storres
            #print scalingFunction
1841 212 storres
            scaledHardToRoundCaseAsFloat = \
1842 212 storres
                scalingFunction(hardToRoundCaseAsFloat)
1843 212 storres
            print "Candidate HTRNc at x =", \
1844 212 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
1845 212 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
1846 212 storres
                           function,
1847 212 storres
                           2^-(targetHardnessToRound),
1848 212 storres
                           RRR):
1849 212 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
1850 212 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
1851 212 storres
                    print "Found in interval."
1852 212 storres
                else:
1853 212 storres
                    print "Found out of interval."
1854 212 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
1855 212 storres
                # Check the root is in the bounds
1856 212 storres
                if abs(root[0]) > iBound or abs(root[1]) > tBound:
1857 212 storres
                    print "Root", root, "is out of bounds for modular equation."
1858 212 storres
                    if abs(root[0]) > iBound:
1859 212 storres
                        print "root[0]:", root[0]
1860 212 storres
                        print "i bound:", iBound
1861 212 storres
                        failingBounds.append('i')
1862 212 storres
                        failingBounds.append(root[0])
1863 212 storres
                        failingBounds.append(iBound)
1864 212 storres
                    if abs(root[1]) > tBound:
1865 212 storres
                        print "root[1]:", root[1]
1866 212 storres
                        print "t bound:", tBound
1867 212 storres
                        failingBounds.append('t')
1868 212 storres
                        failingBounds.append(root[1])
1869 212 storres
                        failingBounds.append(tBound)
1870 212 storres
                if len(failingBounds) > 0:
1871 212 storres
                    specificRootResultsList.append(failingBounds)
1872 212 storres
            else: # From slz_is_htrn...
1873 212 storres
                print "is not an HTRN case."
1874 212 storres
            if len(specificRootResultsList) > 0:
1875 212 storres
                rootsResultsList.append(specificRootResultsList)
1876 212 storres
        if len(rootsResultsList) > 0:
1877 212 storres
            intervalResultsList.append(rootsResultsList)
1878 212 storres
        ### Check if a non null resultant was found. If not shrink the interval.
1879 212 storres
        if not hasNonNullResultant:
1880 212 storres
            print "Only null resultants for this reduction, shrinking interval."
1881 212 storres
            resultCondFailed      =  True
1882 212 storres
            resultCondFailedCount += 1
1883 212 storres
            ### Shrink interval for next iteration.
1884 212 storres
            ub = lb + bw * onlyNullResultantsShrink
1885 212 storres
            if ub > sdub:
1886 212 storres
                ub = sdub
1887 212 storres
            nbw = 0
1888 212 storres
            continue
1889 212 storres
        #### An intervalResultsList has at least the bounds.
1890 212 storres
        globalResultsList.append(intervalResultsList)
1891 212 storres
        #### Compute an incremented width for next upper bound, only
1892 212 storres
        #    if not Coppersmith condition nor resultant condition
1893 212 storres
        #    failed at the previous run.
1894 212 storres
        if not coppCondFailed and not resultCondFailed:
1895 212 storres
            nbw = noErrorIntervalStretch * bw
1896 212 storres
        else:
1897 212 storres
            nbw = bw
1898 212 storres
        ##### Reset the failure flags. They will be raised
1899 212 storres
        #     again if needed.
1900 212 storres
        coppCondFailed   = False
1901 212 storres
        resultCondFailed = False
1902 212 storres
        #### For next iteration (at end of loop)
1903 212 storres
        #print "nbw:", nbw
1904 212 storres
        lb  = ub
1905 212 storres
        ub += nbw
1906 212 storres
        if ub > sdub:
1907 212 storres
            ub = sdub
1908 212 storres
        print
1909 212 storres
    # End while True
1910 212 storres
    ## Main loop just ended.
1911 212 storres
    globalWallTime = walltime(wallTimeStart)
1912 212 storres
    globalCpuTime  = cputime(cpuTimeStart)
1913 212 storres
    ## Output results
1914 212 storres
    print ; print "Intervals and HTRNs" ; print
1915 212 storres
    for intervalResultsList in globalResultsList:
1916 222 storres
        intervalResultString = "[" + str(intervalResultsList[0][0]) +\
1917 222 storres
                               "," + str(intervalResultsList[0][1])  + "]"
1918 222 storres
        print intervalResultString,
1919 212 storres
        if len(intervalResultsList) > 1:
1920 212 storres
            rootsResultsList = intervalResultsList[1]
1921 222 storres
            specificRootResultIndex = 0
1922 212 storres
            for specificRootResultsList in rootsResultsList:
1923 222 storres
                if specificRootResultIndex == 0:
1924 222 storres
                    print "\t", specificRootResultsList[0],
1925 222 storres
                else:
1926 222 storres
                    print " " * len(intervalResultString), "\t", \
1927 222 storres
                          specificRootResultsList[0],
1928 212 storres
                if len(specificRootResultsList) > 1:
1929 222 storres
                    print specificRootResultsList[1]
1930 222 storres
                specificRootResultIndex += 1
1931 212 storres
        print ; print
1932 212 storres
    #print globalResultsList
1933 212 storres
    #
1934 212 storres
    print "Timers and counters"
1935 212 storres
    print
1936 212 storres
    print "Number of iterations:", iterCount
1937 212 storres
    print "Taylor condition failures:", taylCondFailedCount
1938 212 storres
    print "Coppersmith condition failures:", coppCondFailedCount
1939 212 storres
    print "Resultant condition failures:", resultCondFailedCount
1940 212 storres
    print "Iterations count: ", iterCount
1941 212 storres
    print "Number of intervals:", len(globalResultsList)
1942 212 storres
    print "Number of basis constructions:", basisConstructionsCount
1943 212 storres
    print "Total CPU time spent in basis constructions:", \
1944 212 storres
        basisConstructionsFullTime
1945 212 storres
    if basisConstructionsCount != 0:
1946 212 storres
        print "Average basis construction CPU time:", \
1947 212 storres
            basisConstructionsFullTime/basisConstructionsCount
1948 212 storres
    print "Number of reductions:", reductionsCount
1949 212 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
1950 212 storres
    if reductionsCount != 0:
1951 212 storres
        print "Average reduction CPU time:", \
1952 212 storres
            reductionsFullTime/reductionsCount
1953 212 storres
    print "Number of resultants computation rounds:", \
1954 212 storres
        resultantsComputationsCount
1955 212 storres
    print "Total CPU time spent in resultants computation rounds:", \
1956 212 storres
        resultantsComputationsFullTime
1957 212 storres
    if resultantsComputationsCount != 0:
1958 212 storres
        print "Average resultants computation round CPU time:", \
1959 212 storres
            resultantsComputationsFullTime/resultantsComputationsCount
1960 212 storres
    print "Number of root finding rounds:", rootsComputationsCount
1961 212 storres
    print "Total CPU time spent in roots finding rounds:", \
1962 212 storres
        rootsComputationsFullTime
1963 212 storres
    if rootsComputationsCount != 0:
1964 212 storres
        print "Average roots finding round CPU time:", \
1965 212 storres
            rootsComputationsFullTime/rootsComputationsCount
1966 212 storres
    print "Global Wall time:", globalWallTime
1967 212 storres
    print "Global CPU time:", globalCpuTime
1968 212 storres
    ## Output counters
1969 212 storres
# End srs_runSLZ-v03
1970 212 storres
1971 213 storres
def srs_run_SLZ_v04(inputFunction,
1972 212 storres
                    inputLowerBound,
1973 212 storres
                    inputUpperBound,
1974 212 storres
                    alpha,
1975 212 storres
                    degree,
1976 212 storres
                    precision,
1977 212 storres
                    emin,
1978 212 storres
                    emax,
1979 212 storres
                    targetHardnessToRound,
1980 212 storres
                    debug = False):
1981 212 storres
    """
1982 213 storres
    Changes from V3:
1983 213 storres
        Root search is changed again:
1984 213 storres
            - only resultants in i are computed;
1985 219 storres
            - roots in i are searched for;
1986 213 storres
            - if any, they are tested for hardness-to-round.
1987 212 storres
    Changes from V2:
1988 212 storres
        Root search is changed:
1989 212 storres
            - we compute the resultants in i and in t;
1990 212 storres
            - we compute the roots set of each of these resultants;
1991 212 storres
            - we combine all the possible pairs between the two sets;
1992 212 storres
            - we check these pairs in polynomials for correctness.
1993 212 storres
    Changes from V1:
1994 212 storres
        1- check for roots as soon as a resultant is computed;
1995 212 storres
        2- once a non null resultant is found, check for roots;
1996 212 storres
        3- constant resultant == no root.
1997 212 storres
    """
1998 212 storres
1999 212 storres
    if debug:
2000 212 storres
        print "Function                :", inputFunction
2001 212 storres
        print "Lower bound             :", inputLowerBound
2002 212 storres
        print "Upper bounds            :", inputUpperBound
2003 212 storres
        print "Alpha                   :", alpha
2004 212 storres
        print "Degree                  :", degree
2005 212 storres
        print "Precision               :", precision
2006 212 storres
        print "Emin                    :", emin
2007 212 storres
        print "Emax                    :", emax
2008 212 storres
        print "Target hardness-to-round:", targetHardnessToRound
2009 212 storres
        print
2010 212 storres
    ## Important constants.
2011 212 storres
    ### Stretch the interval if no error happens.
2012 212 storres
    noErrorIntervalStretch = 1 + 2^(-5)
2013 212 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
2014 212 storres
    #   by the following factor.
2015 212 storres
    noCoppersmithIntervalShrink = 1/2
2016 212 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
2017 212 storres
    #   shrink the interval by the following factor.
2018 212 storres
    oneCoppersmithIntervalShrink = 3/4
2019 212 storres
    #### If only null resultants are found, shrink the interval by the
2020 212 storres
    #    following factor.
2021 212 storres
    onlyNullResultantsShrink     = 3/4
2022 212 storres
    ## Structures.
2023 212 storres
    RRR         = RealField(precision)
2024 212 storres
    RRIF        = RealIntervalField(precision)
2025 212 storres
    ## Converting input bound into the "right" field.
2026 212 storres
    lowerBound = RRR(inputLowerBound)
2027 212 storres
    upperBound = RRR(inputUpperBound)
2028 212 storres
    ## Before going any further, check domain and image binade conditions.
2029 212 storres
    print inputFunction(1).n()
2030 212 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
2031 212 storres
    if output is None:
2032 212 storres
        print "Invalid domain/image binades. Domain:",\
2033 212 storres
        lowerBound, upperBound, "Images:", \
2034 212 storres
        inputFunction(lowerBound), inputFunction(upperBound)
2035 212 storres
        raise Exception("Invalid domain/image binades.")
2036 212 storres
    lb = output[0] ; ub = output[1]
2037 212 storres
    if lb != lowerBound or ub != upperBound:
2038 212 storres
        print "lb:", lb, " - ub:", ub
2039 212 storres
        print "Invalid domain/image binades. Domain:",\
2040 212 storres
        lowerBound, upperBound, "Images:", \
2041 212 storres
        inputFunction(lowerBound), inputFunction(upperBound)
2042 212 storres
        raise Exception("Invalid domain/image binades.")
2043 212 storres
    #
2044 212 storres
    ## Progam initialization
2045 212 storres
    ### Approximation polynomial accuracy and hardness to round.
2046 212 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
2047 212 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
2048 212 storres
    ### Significand to integer conversion ratio.
2049 212 storres
    toIntegerFactor           = 2^(precision-1)
2050 212 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
2051 212 storres
    ### Variables and rings for polynomials and root searching.
2052 212 storres
    i=var('i')
2053 212 storres
    t=var('t')
2054 212 storres
    inputFunctionVariable = inputFunction.variables()[0]
2055 212 storres
    function = inputFunction.subs({inputFunctionVariable:i})
2056 212 storres
    #  Polynomial Rings over the integers, for root finding.
2057 212 storres
    Zi = ZZ[i]
2058 212 storres
    Zt = ZZ[t]
2059 212 storres
    Zit = ZZ[i,t]
2060 212 storres
    ## Number of iterations limit.
2061 212 storres
    maxIter = 100000
2062 212 storres
    #
2063 212 storres
    ## Compute the scaled function and the degree, in their Sollya version
2064 212 storres
    #  once for all.
2065 212 storres
    (scaledf, sdlb, sdub, silb, siub) = \
2066 212 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
2067 212 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
2068 212 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
2069 212 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
2070 212 storres
    #
2071 212 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
2072 212 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
2073 212 storres
    (unscalingFunction, scalingFunction) = \
2074 212 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
2075 212 storres
    #print scalingFunction, unscalingFunction
2076 212 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
2077 212 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
2078 212 storres
    if internalSollyaPrec < 192:
2079 212 storres
        internalSollyaPrec = 192
2080 212 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
2081 212 storres
    print "Sollya internal precision:", internalSollyaPrec
2082 212 storres
    ## Some variables.
2083 212 storres
    ### General variables
2084 212 storres
    lb                  = sdlb
2085 212 storres
    ub                  = sdub
2086 212 storres
    nbw                 = 0
2087 212 storres
    intervalUlp         = ub.ulp()
2088 212 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
2089 212 storres
    ic                  = 0
2090 212 storres
    icAsInt             = 0    # Set from ic.
2091 212 storres
    solutionsSet        = set()
2092 212 storres
    tsErrorWidth        = []
2093 212 storres
    csErrorVectors      = []
2094 212 storres
    csVectorsResultants = []
2095 212 storres
    floatP              = 0  # Taylor polynomial.
2096 212 storres
    floatPcv            = 0  # Ditto with variable change.
2097 212 storres
    intvl               = "" # Taylor interval
2098 212 storres
    terr                = 0  # Taylor error.
2099 212 storres
    iterCount = 0
2100 212 storres
    htrnSet = set()
2101 212 storres
    ### Timers and counters.
2102 212 storres
    wallTimeStart                   = 0
2103 212 storres
    cpuTimeStart                    = 0
2104 212 storres
    taylCondFailedCount             = 0
2105 212 storres
    coppCondFailedCount             = 0
2106 212 storres
    resultCondFailedCount           = 0
2107 212 storres
    coppCondFailed                  = False
2108 212 storres
    resultCondFailed                = False
2109 212 storres
    globalResultsList               = []
2110 212 storres
    basisConstructionsCount         = 0
2111 212 storres
    basisConstructionsFullTime      = 0
2112 212 storres
    basisConstructionTime           = 0
2113 212 storres
    reductionsCount                 = 0
2114 212 storres
    reductionsFullTime              = 0
2115 212 storres
    reductionTime                   = 0
2116 212 storres
    resultantsComputationsCount     = 0
2117 212 storres
    resultantsComputationsFullTime  = 0
2118 212 storres
    resultantsComputationTime       = 0
2119 212 storres
    rootsComputationsCount          = 0
2120 212 storres
    rootsComputationsFullTime       = 0
2121 212 storres
    rootsComputationTime            = 0
2122 212 storres
    print
2123 212 storres
    ## Global times are started here.
2124 212 storres
    wallTimeStart                   = walltime()
2125 212 storres
    cpuTimeStart                    = cputime()
2126 212 storres
    ## Main loop.
2127 212 storres
    while True:
2128 212 storres
        if lb >= sdub:
2129 212 storres
            print "Lower bound reached upper bound."
2130 212 storres
            break
2131 212 storres
        if iterCount == maxIter:
2132 212 storres
            print "Reached maxIter. Aborting"
2133 212 storres
            break
2134 212 storres
        iterCount += 1
2135 212 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
2136 212 storres
            "log2(numbers)."
2137 212 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
2138 212 storres
        prceSo = slz_compute_polynomial_and_interval(scaledfSo,
2139 212 storres
                                                     degreeSo,
2140 212 storres
                                                     lb,
2141 212 storres
                                                     ub,
2142 212 storres
                                                     polyApproxAccur)
2143 212 storres
        ### Convert back the data into Sage space.
2144 212 storres
        (floatP, floatPcv, intvl, ic, terr) = \
2145 212 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
2146 212 storres
                                                 prceSo[1], prceSo[2],
2147 212 storres
                                                 prceSo[3]))
2148 212 storres
        intvl = RRIF(intvl)
2149 212 storres
        ## Clean-up Sollya stuff.
2150 212 storres
        for elem in prceSo:
2151 212 storres
            sollya_lib_clear_obj(elem)
2152 212 storres
        #print  floatP, floatPcv, intvl, ic, terr
2153 212 storres
        #print floatP
2154 212 storres
        #print intvl.endpoints()[0].n(), \
2155 212 storres
        #      ic.n(),
2156 212 storres
        #intvl.endpoints()[1].n()
2157 212 storres
        ### Check returned data.
2158 212 storres
        #### Is approximation error OK?
2159 212 storres
        if terr > polyApproxAccur:
2160 212 storres
            exceptionErrorMess  = \
2161 212 storres
                "Approximation failed - computed error:" + \
2162 212 storres
                str(terr) + " - target error: "
2163 212 storres
            exceptionErrorMess += \
2164 212 storres
                str(polyApproxAccur) + ". Aborting!"
2165 212 storres
            raise Exception(exceptionErrorMess)
2166 212 storres
        #### Is lower bound OK?
2167 212 storres
        if lb != intvl.endpoints()[0]:
2168 212 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
2169 212 storres
                               str(lb) + ". Aborting!"
2170 212 storres
            raise Exception(exceptionErrorMess)
2171 212 storres
        #### Set upper bound.
2172 212 storres
        if ub > intvl.endpoints()[1]:
2173 212 storres
            ub = intvl.endpoints()[1]
2174 212 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
2175 212 storres
            "log2(numbers)."
2176 212 storres
            taylCondFailedCount += 1
2177 212 storres
        #### Is interval not degenerate?
2178 212 storres
        if lb >= ub:
2179 212 storres
            exceptionErrorMess = "Degenerate interval: " + \
2180 212 storres
                                "lowerBound(" + str(lb) +\
2181 212 storres
                                ")>= upperBound(" + str(ub) + \
2182 212 storres
                                "). Aborting!"
2183 212 storres
            raise Exception(exceptionErrorMess)
2184 212 storres
        #### Is interval center ok?
2185 212 storres
        if ic <= lb or ic >= ub:
2186 212 storres
            exceptionErrorMess =  "Invalid interval center for " + \
2187 212 storres
                                str(lb) + ',' + str(ic) + ',' +  \
2188 212 storres
                                str(ub) + ". Aborting!"
2189 212 storres
            raise Exception(exceptionErrorMess)
2190 212 storres
        ##### Current interval width and reset future interval width.
2191 212 storres
        bw = ub - lb
2192 212 storres
        nbw = 0
2193 212 storres
        icAsInt = int(ic * toIntegerFactor)
2194 212 storres
        #### The following ratio is always >= 1. In case we may want to
2195 212 storres
        #    enlarge the interval
2196 212 storres
        curTaylErrRat = polyApproxAccur / terr
2197 212 storres
        ### Make the  integral transformations.
2198 212 storres
        #### Bounds and interval center.
2199 212 storres
        intIc = int(ic * toIntegerFactor)
2200 212 storres
        intLb = int(lb * toIntegerFactor) - intIc
2201 212 storres
        intUb = int(ub * toIntegerFactor) - intIc
2202 212 storres
        #
2203 212 storres
        #### Polynomials
2204 212 storres
        basisConstructionTime         = cputime()
2205 212 storres
        ##### To a polynomial with rational coefficients with rational arguments
2206 212 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
2207 212 storres
        ##### To a polynomial with rational coefficients with integer arguments
2208 212 storres
        ratIntP = \
2209 212 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
2210 212 storres
        #####  Ultimately a multivariate polynomial with integer coefficients
2211 212 storres
        #      with integer arguments.
2212 212 storres
        coppersmithTuple = \
2213 212 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
2214 212 storres
                                                        precision,
2215 212 storres
                                                        targetHardnessToRound,
2216 212 storres
                                                        i, t)
2217 212 storres
        #### Recover Coppersmith information.
2218 212 storres
        intIntP = coppersmithTuple[0]
2219 212 storres
        N = coppersmithTuple[1]
2220 212 storres
        nAtAlpha = N^alpha
2221 212 storres
        tBound = coppersmithTuple[2]
2222 212 storres
        leastCommonMultiple = coppersmithTuple[3]
2223 212 storres
        iBound = max(abs(intLb),abs(intUb))
2224 212 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
2225 212 storres
        basisConstructionsCount           += 1
2226 212 storres
        reductionTime                     = cputime()
2227 212 storres
        #### Compute the reduced polynomials.
2228 212 storres
        ccReducedPolynomialsList =  \
2229 213 storres
                slz_compute_coppersmith_reduced_polynomials(intIntP,
2230 213 storres
                                                            alpha,
2231 213 storres
                                                            N,
2232 213 storres
                                                            iBound,
2233 213 storres
                                                            tBound)
2234 212 storres
        if ccReducedPolynomialsList is None:
2235 212 storres
            raise Exception("Reduction failed.")
2236 212 storres
        reductionsFullTime    += cputime(reductionTime)
2237 212 storres
        reductionsCount       += 1
2238 212 storres
        if len(ccReducedPolynomialsList) < 2:
2239 212 storres
            print "Nothing to form resultants with."
2240 212 storres
            print
2241 212 storres
            coppCondFailedCount += 1
2242 212 storres
            coppCondFailed = True
2243 212 storres
            ##### Apply a different shrink factor according to
2244 212 storres
            #  the number of compliant polynomials.
2245 212 storres
            if len(ccReducedPolynomialsList) == 0:
2246 212 storres
                ub = lb + bw * noCoppersmithIntervalShrink
2247 212 storres
            else: # At least one compliant polynomial.
2248 212 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
2249 212 storres
            if ub > sdub:
2250 212 storres
                ub = sdub
2251 212 storres
            if lb == ub:
2252 212 storres
                raise Exception("Cant shrink interval \
2253 212 storres
                anymore to get Coppersmith condition.")
2254 212 storres
            nbw = 0
2255 212 storres
            continue
2256 212 storres
        #### We have at least two polynomials.
2257 212 storres
        #    Let us try to compute resultants.
2258 212 storres
        #    For each resultant computed, go for the solutions.
2259 212 storres
        ##### Build the pairs list.
2260 212 storres
        polyPairsList           = []
2261 212 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
2262 212 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
2263 212 storres
                                         len(ccReducedPolynomialsList)):
2264 212 storres
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
2265 212 storres
                                      ccReducedPolynomialsList[polyInnerIndex]))
2266 212 storres
        #### Actual root search.
2267 213 storres
        iRootsSet           = set()
2268 212 storres
        hasNonNullResultant = False
2269 212 storres
        for polyPair in polyPairsList:
2270 212 storres
            resultantsComputationTime   = cputime()
2271 212 storres
            currentResultantI = \
2272 212 storres
                slz_resultant(polyPair[0],
2273 212 storres
                              polyPair[1],
2274 212 storres
                              t)
2275 212 storres
            resultantsComputationsCount    += 1
2276 213 storres
            resultantsComputationsFullTime +=  \
2277 213 storres
                cputime(resultantsComputationTime)
2278 213 storres
            #### Function slz_resultant returns None both for None and O
2279 213 storres
            #    resultants.
2280 212 storres
            if currentResultantI is None:
2281 212 storres
                print "Nul resultant"
2282 212 storres
                continue # Next polyPair.
2283 213 storres
            ## We deleted the currentResultantI computation.
2284 213 storres
            #### We have a non null resultant. From now on, whatever this
2285 212 storres
            #    root search yields, no extra root search is necessary.
2286 213 storres
            hasNonNullResultant = True
2287 212 storres
            #### A constant resultant leads to no root. Root search is done.
2288 212 storres
            if currentResultantI.degree() < 1:
2289 212 storres
                print "Resultant is constant:", currentResultantI
2290 213 storres
                break # There is no root.
2291 213 storres
            #### Actual iroots computation.
2292 213 storres
            rootsComputationTime        = cputime()
2293 212 storres
            iRootsList = Zi(currentResultantI).roots()
2294 212 storres
            rootsComputationsCount      +=  1
2295 213 storres
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
2296 212 storres
            if len(iRootsList) == 0:
2297 212 storres
                print "No roots in \"i\"."
2298 212 storres
                break # No roots in i.
2299 213 storres
            else:
2300 213 storres
                for iRoot in iRootsList:
2301 213 storres
                    # A root is given as a (value, multiplicity) tuple.
2302 213 storres
                    iRootsSet.add(iRoot[0])
2303 213 storres
        # End loop for polyPair in polyParsList. We only loop again if a
2304 213 storres
        # None or zero resultant is found.
2305 212 storres
        #### Prepare for results for the current interval..
2306 212 storres
        intervalResultsList = []
2307 212 storres
        intervalResultsList.append((lb, ub))
2308 212 storres
        #### Check roots.
2309 212 storres
        rootsResultsList = []
2310 213 storres
        for iRoot in iRootsSet:
2311 212 storres
            specificRootResultsList = []
2312 213 storres
            failingBounds           = []
2313 212 storres
            # Root qualifies for modular equation, test it for hardness to round.
2314 213 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + iRoot) / toIntegerFactor)
2315 212 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
2316 212 storres
            #print scalingFunction
2317 212 storres
            scaledHardToRoundCaseAsFloat = \
2318 212 storres
                scalingFunction(hardToRoundCaseAsFloat)
2319 212 storres
            print "Candidate HTRNc at x =", \
2320 212 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
2321 212 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
2322 212 storres
                           function,
2323 212 storres
                           2^-(targetHardnessToRound),
2324 212 storres
                           RRR):
2325 212 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
2326 213 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
2327 212 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
2328 212 storres
                    print "Found in interval."
2329 212 storres
                else:
2330 212 storres
                    print "Found out of interval."
2331 213 storres
                # Check the i root is within the i bound.
2332 213 storres
                if abs(iRoot) > iBound:
2333 213 storres
                    print "IRoot", iRoot, "is out of bounds for modular equation."
2334 213 storres
                    print "i bound:", iBound
2335 213 storres
                    failingBounds.append('i')
2336 213 storres
                    failingBounds.append(iRoot)
2337 213 storres
                    failingBounds.append(iBound)
2338 212 storres
                if len(failingBounds) > 0:
2339 212 storres
                    specificRootResultsList.append(failingBounds)
2340 212 storres
            else: # From slz_is_htrn...
2341 212 storres
                print "is not an HTRN case."
2342 212 storres
            if len(specificRootResultsList) > 0:
2343 212 storres
                rootsResultsList.append(specificRootResultsList)
2344 212 storres
        if len(rootsResultsList) > 0:
2345 212 storres
            intervalResultsList.append(rootsResultsList)
2346 212 storres
        ### Check if a non null resultant was found. If not shrink the interval.
2347 212 storres
        if not hasNonNullResultant:
2348 212 storres
            print "Only null resultants for this reduction, shrinking interval."
2349 212 storres
            resultCondFailed      =  True
2350 212 storres
            resultCondFailedCount += 1
2351 212 storres
            ### Shrink interval for next iteration.
2352 212 storres
            ub = lb + bw * onlyNullResultantsShrink
2353 212 storres
            if ub > sdub:
2354 212 storres
                ub = sdub
2355 212 storres
            nbw = 0
2356 212 storres
            continue
2357 212 storres
        #### An intervalResultsList has at least the bounds.
2358 212 storres
        globalResultsList.append(intervalResultsList)
2359 212 storres
        #### Compute an incremented width for next upper bound, only
2360 212 storres
        #    if not Coppersmith condition nor resultant condition
2361 212 storres
        #    failed at the previous run.
2362 212 storres
        if not coppCondFailed and not resultCondFailed:
2363 212 storres
            nbw = noErrorIntervalStretch * bw
2364 212 storres
        else:
2365 212 storres
            nbw = bw
2366 212 storres
        ##### Reset the failure flags. They will be raised
2367 212 storres
        #     again if needed.
2368 212 storres
        coppCondFailed   = False
2369 212 storres
        resultCondFailed = False
2370 212 storres
        #### For next iteration (at end of loop)
2371 212 storres
        #print "nbw:", nbw
2372 212 storres
        lb  = ub
2373 212 storres
        ub += nbw
2374 212 storres
        if ub > sdub:
2375 212 storres
            ub = sdub
2376 212 storres
        print
2377 212 storres
    # End while True
2378 212 storres
    ## Main loop just ended.
2379 212 storres
    globalWallTime = walltime(wallTimeStart)
2380 212 storres
    globalCpuTime  = cputime(cpuTimeStart)
2381 212 storres
    ## Output results
2382 212 storres
    print ; print "Intervals and HTRNs" ; print
2383 212 storres
    for intervalResultsList in globalResultsList:
2384 222 storres
        intervalResultString = "[" + str(intervalResultsList[0][0]) +\
2385 222 storres
                               "," + str(intervalResultsList[0][1])  + "]"
2386 222 storres
        print intervalResultString,
2387 212 storres
        if len(intervalResultsList) > 1:
2388 212 storres
            rootsResultsList = intervalResultsList[1]
2389 222 storres
            specificRootResultIndex = 0
2390 212 storres
            for specificRootResultsList in rootsResultsList:
2391 222 storres
                if specificRootResultIndex == 0:
2392 222 storres
                    print "\t", specificRootResultsList[0],
2393 222 storres
                else:
2394 222 storres
                    print " " * len(intervalResultString), "\t", \
2395 222 storres
                          specificRootResultsList[0],
2396 212 storres
                if len(specificRootResultsList) > 1:
2397 222 storres
                    print specificRootResultsList[1]
2398 222 storres
                specificRootResultIndex += 1
2399 212 storres
        print ; print
2400 212 storres
    #print globalResultsList
2401 212 storres
    #
2402 212 storres
    print "Timers and counters"
2403 212 storres
    print
2404 212 storres
    print "Number of iterations:", iterCount
2405 212 storres
    print "Taylor condition failures:", taylCondFailedCount
2406 212 storres
    print "Coppersmith condition failures:", coppCondFailedCount
2407 212 storres
    print "Resultant condition failures:", resultCondFailedCount
2408 212 storres
    print "Iterations count: ", iterCount
2409 212 storres
    print "Number of intervals:", len(globalResultsList)
2410 212 storres
    print "Number of basis constructions:", basisConstructionsCount
2411 212 storres
    print "Total CPU time spent in basis constructions:", \
2412 212 storres
        basisConstructionsFullTime
2413 212 storres
    if basisConstructionsCount != 0:
2414 212 storres
        print "Average basis construction CPU time:", \
2415 212 storres
            basisConstructionsFullTime/basisConstructionsCount
2416 212 storres
    print "Number of reductions:", reductionsCount
2417 212 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
2418 212 storres
    if reductionsCount != 0:
2419 212 storres
        print "Average reduction CPU time:", \
2420 212 storres
            reductionsFullTime/reductionsCount
2421 212 storres
    print "Number of resultants computation rounds:", \
2422 212 storres
        resultantsComputationsCount
2423 212 storres
    print "Total CPU time spent in resultants computation rounds:", \
2424 212 storres
        resultantsComputationsFullTime
2425 212 storres
    if resultantsComputationsCount != 0:
2426 212 storres
        print "Average resultants computation round CPU time:", \
2427 212 storres
            resultantsComputationsFullTime/resultantsComputationsCount
2428 212 storres
    print "Number of root finding rounds:", rootsComputationsCount
2429 212 storres
    print "Total CPU time spent in roots finding rounds:", \
2430 212 storres
        rootsComputationsFullTime
2431 212 storres
    if rootsComputationsCount != 0:
2432 212 storres
        print "Average roots finding round CPU time:", \
2433 212 storres
            rootsComputationsFullTime/rootsComputationsCount
2434 212 storres
    print "Global Wall time:", globalWallTime
2435 212 storres
    print "Global CPU time:", globalCpuTime
2436 212 storres
    ## Output counters
2437 213 storres
# End srs_runSLZ-v04
2438 213 storres
2439 219 storres
def srs_run_SLZ_v05(inputFunction,
2440 219 storres
                    inputLowerBound,
2441 219 storres
                    inputUpperBound,
2442 219 storres
                    alpha,
2443 219 storres
                    degree,
2444 219 storres
                    precision,
2445 219 storres
                    emin,
2446 219 storres
                    emax,
2447 219 storres
                    targetHardnessToRound,
2448 219 storres
                    debug = False):
2449 219 storres
    """
2450 219 storres
    Changes from V4:
2451 219 storres
        Approximation polynomial has coefficients rounded.
2452 219 storres
    Changes from V3:
2453 219 storres
        Root search is changed again:
2454 219 storres
            - only resultants in i are computed;
2455 219 storres
            - roots in i are searched for;
2456 219 storres
            - if any, they are tested for hardness-to-round.
2457 219 storres
    Changes from V2:
2458 219 storres
        Root search is changed:
2459 219 storres
            - we compute the resultants in i and in t;
2460 219 storres
            - we compute the roots set of each of these resultants;
2461 219 storres
            - we combine all the possible pairs between the two sets;
2462 219 storres
            - we check these pairs in polynomials for correctness.
2463 219 storres
    Changes from V1:
2464 219 storres
        1- check for roots as soon as a resultant is computed;
2465 219 storres
        2- once a non null resultant is found, check for roots;
2466 219 storres
        3- constant resultant == no root.
2467 219 storres
    """
2468 219 storres
2469 219 storres
    if debug:
2470 219 storres
        print "Function                :", inputFunction
2471 219 storres
        print "Lower bound             :", inputLowerBound
2472 219 storres
        print "Upper bounds            :", inputUpperBound
2473 219 storres
        print "Alpha                   :", alpha
2474 219 storres
        print "Degree                  :", degree
2475 219 storres
        print "Precision               :", precision
2476 219 storres
        print "Emin                    :", emin
2477 219 storres
        print "Emax                    :", emax
2478 219 storres
        print "Target hardness-to-round:", targetHardnessToRound
2479 219 storres
        print
2480 219 storres
    ## Important constants.
2481 219 storres
    ### Stretch the interval if no error happens.
2482 219 storres
    noErrorIntervalStretch = 1 + 2^(-5)
2483 219 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
2484 219 storres
    #   by the following factor.
2485 219 storres
    noCoppersmithIntervalShrink = 1/2
2486 219 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
2487 219 storres
    #   shrink the interval by the following factor.
2488 219 storres
    oneCoppersmithIntervalShrink = 3/4
2489 219 storres
    #### If only null resultants are found, shrink the interval by the
2490 219 storres
    #    following factor.
2491 219 storres
    onlyNullResultantsShrink     = 3/4
2492 219 storres
    ## Structures.
2493 219 storres
    RRR         = RealField(precision)
2494 219 storres
    RRIF        = RealIntervalField(precision)
2495 219 storres
    ## Converting input bound into the "right" field.
2496 219 storres
    lowerBound = RRR(inputLowerBound)
2497 219 storres
    upperBound = RRR(inputUpperBound)
2498 219 storres
    ## Before going any further, check domain and image binade conditions.
2499 219 storres
    print inputFunction(1).n()
2500 219 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
2501 219 storres
    if output is None:
2502 219 storres
        print "Invalid domain/image binades. Domain:",\
2503 219 storres
        lowerBound, upperBound, "Images:", \
2504 219 storres
        inputFunction(lowerBound), inputFunction(upperBound)
2505 219 storres
        raise Exception("Invalid domain/image binades.")
2506 219 storres
    lb = output[0] ; ub = output[1]
2507 219 storres
    if lb != lowerBound or ub != upperBound:
2508 219 storres
        print "lb:", lb, " - ub:", ub
2509 219 storres
        print "Invalid domain/image binades. Domain:",\
2510 219 storres
        lowerBound, upperBound, "Images:", \
2511 219 storres
        inputFunction(lowerBound), inputFunction(upperBound)
2512 219 storres
        raise Exception("Invalid domain/image binades.")
2513 219 storres
    #
2514 219 storres
    ## Progam initialization
2515 219 storres
    ### Approximation polynomial accuracy and hardness to round.
2516 219 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
2517 219 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
2518 219 storres
    ### Significand to integer conversion ratio.
2519 219 storres
    toIntegerFactor           = 2^(precision-1)
2520 219 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
2521 219 storres
    ### Variables and rings for polynomials and root searching.
2522 219 storres
    i=var('i')
2523 219 storres
    t=var('t')
2524 219 storres
    inputFunctionVariable = inputFunction.variables()[0]
2525 219 storres
    function = inputFunction.subs({inputFunctionVariable:i})
2526 219 storres
    #  Polynomial Rings over the integers, for root finding.
2527 219 storres
    Zi = ZZ[i]
2528 219 storres
    Zt = ZZ[t]
2529 219 storres
    Zit = ZZ[i,t]
2530 219 storres
    ## Number of iterations limit.
2531 219 storres
    maxIter = 100000
2532 219 storres
    #
2533 219 storres
    ## Compute the scaled function and the degree, in their Sollya version
2534 219 storres
    #  once for all.
2535 219 storres
    (scaledf, sdlb, sdub, silb, siub) = \
2536 219 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
2537 219 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
2538 219 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
2539 219 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
2540 219 storres
    #
2541 219 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
2542 219 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
2543 219 storres
    (unscalingFunction, scalingFunction) = \
2544 219 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
2545 219 storres
    #print scalingFunction, unscalingFunction
2546 219 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
2547 219 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
2548 219 storres
    if internalSollyaPrec < 192:
2549 219 storres
        internalSollyaPrec = 192
2550 219 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
2551 219 storres
    print "Sollya internal precision:", internalSollyaPrec
2552 219 storres
    ## Some variables.
2553 219 storres
    ### General variables
2554 219 storres
    lb                  = sdlb
2555 219 storres
    ub                  = sdub
2556 219 storres
    nbw                 = 0
2557 219 storres
    intervalUlp         = ub.ulp()
2558 219 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
2559 219 storres
    ic                  = 0
2560 219 storres
    icAsInt             = 0    # Set from ic.
2561 219 storres
    solutionsSet        = set()
2562 219 storres
    tsErrorWidth        = []
2563 219 storres
    csErrorVectors      = []
2564 219 storres
    csVectorsResultants = []
2565 219 storres
    floatP              = 0  # Taylor polynomial.
2566 219 storres
    floatPcv            = 0  # Ditto with variable change.
2567 219 storres
    intvl               = "" # Taylor interval
2568 219 storres
    terr                = 0  # Taylor error.
2569 219 storres
    iterCount = 0
2570 219 storres
    htrnSet = set()
2571 219 storres
    ### Timers and counters.
2572 219 storres
    wallTimeStart                   = 0
2573 219 storres
    cpuTimeStart                    = 0
2574 219 storres
    taylCondFailedCount             = 0
2575 219 storres
    coppCondFailedCount             = 0
2576 219 storres
    resultCondFailedCount           = 0
2577 219 storres
    coppCondFailed                  = False
2578 219 storres
    resultCondFailed                = False
2579 219 storres
    globalResultsList               = []
2580 219 storres
    basisConstructionsCount         = 0
2581 219 storres
    basisConstructionsFullTime      = 0
2582 219 storres
    basisConstructionTime           = 0
2583 219 storres
    reductionsCount                 = 0
2584 219 storres
    reductionsFullTime              = 0
2585 219 storres
    reductionTime                   = 0
2586 219 storres
    resultantsComputationsCount     = 0
2587 219 storres
    resultantsComputationsFullTime  = 0
2588 219 storres
    resultantsComputationTime       = 0
2589 219 storres
    rootsComputationsCount          = 0
2590 219 storres
    rootsComputationsFullTime       = 0
2591 219 storres
    rootsComputationTime            = 0
2592 219 storres
    print
2593 219 storres
    ## Global times are started here.
2594 219 storres
    wallTimeStart                   = walltime()
2595 219 storres
    cpuTimeStart                    = cputime()
2596 219 storres
    ## Main loop.
2597 219 storres
    while True:
2598 219 storres
        if lb >= sdub:
2599 219 storres
            print "Lower bound reached upper bound."
2600 219 storres
            break
2601 219 storres
        if iterCount == maxIter:
2602 219 storres
            print "Reached maxIter. Aborting"
2603 219 storres
            break
2604 219 storres
        iterCount += 1
2605 219 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
2606 219 storres
            "log2(numbers)."
2607 219 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
2608 219 storres
        prceSo = slz_compute_polynomial_and_interval_01(scaledfSo,
2609 219 storres
                                                        degreeSo,
2610 219 storres
                                                        lb,
2611 219 storres
                                                        ub,
2612 219 storres
                                                        polyApproxAccur)
2613 225 storres
        if prceSo is None:
2614 225 storres
            raise Exception("Could not compute an approximation polynomial.")
2615 219 storres
        ### Convert back the data into Sage space.
2616 219 storres
        (floatP, floatPcv, intvl, ic, terr) = \
2617 219 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
2618 219 storres
                                                 prceSo[1], prceSo[2],
2619 219 storres
                                                 prceSo[3]))
2620 219 storres
        intvl = RRIF(intvl)
2621 219 storres
        ## Clean-up Sollya stuff.
2622 219 storres
        for elem in prceSo:
2623 219 storres
            sollya_lib_clear_obj(elem)
2624 219 storres
        #print  floatP, floatPcv, intvl, ic, terr
2625 219 storres
        #print floatP
2626 219 storres
        #print intvl.endpoints()[0].n(), \
2627 219 storres
        #      ic.n(),
2628 219 storres
        #intvl.endpoints()[1].n()
2629 219 storres
        ### Check returned data.
2630 219 storres
        #### Is approximation error OK?
2631 219 storres
        if terr > polyApproxAccur:
2632 219 storres
            exceptionErrorMess  = \
2633 219 storres
                "Approximation failed - computed error:" + \
2634 219 storres
                str(terr) + " - target error: "
2635 219 storres
            exceptionErrorMess += \
2636 219 storres
                str(polyApproxAccur) + ". Aborting!"
2637 219 storres
            raise Exception(exceptionErrorMess)
2638 219 storres
        #### Is lower bound OK?
2639 219 storres
        if lb != intvl.endpoints()[0]:
2640 219 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
2641 219 storres
                               str(lb) + ". Aborting!"
2642 219 storres
            raise Exception(exceptionErrorMess)
2643 219 storres
        #### Set upper bound.
2644 219 storres
        if ub > intvl.endpoints()[1]:
2645 219 storres
            ub = intvl.endpoints()[1]
2646 219 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
2647 219 storres
            "log2(numbers)."
2648 219 storres
            taylCondFailedCount += 1
2649 219 storres
        #### Is interval not degenerate?
2650 219 storres
        if lb >= ub:
2651 219 storres
            exceptionErrorMess = "Degenerate interval: " + \
2652 219 storres
                                "lowerBound(" + str(lb) +\
2653 219 storres
                                ")>= upperBound(" + str(ub) + \
2654 219 storres
                                "). Aborting!"
2655 219 storres
            raise Exception(exceptionErrorMess)
2656 219 storres
        #### Is interval center ok?
2657 219 storres
        if ic <= lb or ic >= ub:
2658 219 storres
            exceptionErrorMess =  "Invalid interval center for " + \
2659 219 storres
                                str(lb) + ',' + str(ic) + ',' +  \
2660 219 storres
                                str(ub) + ". Aborting!"
2661 219 storres
            raise Exception(exceptionErrorMess)
2662 219 storres
        ##### Current interval width and reset future interval width.
2663 219 storres
        bw = ub - lb
2664 219 storres
        nbw = 0
2665 219 storres
        icAsInt = int(ic * toIntegerFactor)
2666 219 storres
        #### The following ratio is always >= 1. In case we may want to
2667 219 storres
        #    enlarge the interval
2668 219 storres
        curTaylErrRat = polyApproxAccur / terr
2669 219 storres
        ### Make the  integral transformations.
2670 219 storres
        #### Bounds and interval center.
2671 219 storres
        intIc = int(ic * toIntegerFactor)
2672 219 storres
        intLb = int(lb * toIntegerFactor) - intIc
2673 219 storres
        intUb = int(ub * toIntegerFactor) - intIc
2674 219 storres
        #
2675 219 storres
        #### Polynomials
2676 219 storres
        basisConstructionTime         = cputime()
2677 219 storres
        ##### To a polynomial with rational coefficients with rational arguments
2678 219 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
2679 219 storres
        ##### To a polynomial with rational coefficients with integer arguments
2680 219 storres
        ratIntP = \
2681 219 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
2682 219 storres
        #####  Ultimately a multivariate polynomial with integer coefficients
2683 219 storres
        #      with integer arguments.
2684 219 storres
        coppersmithTuple = \
2685 219 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
2686 219 storres
                                                        precision,
2687 219 storres
                                                        targetHardnessToRound,
2688 219 storres
                                                        i, t)
2689 219 storres
        #### Recover Coppersmith information.
2690 219 storres
        intIntP = coppersmithTuple[0]
2691 219 storres
        N = coppersmithTuple[1]
2692 219 storres
        nAtAlpha = N^alpha
2693 219 storres
        tBound = coppersmithTuple[2]
2694 219 storres
        leastCommonMultiple = coppersmithTuple[3]
2695 219 storres
        iBound = max(abs(intLb),abs(intUb))
2696 219 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
2697 219 storres
        basisConstructionsCount           += 1
2698 224 storres
        #### Compute the matrix to reduce for debug purpose. Otherwise
2699 224 storres
        #    slz_compute_coppersmith_reduced_polynomials does the job
2700 224 storres
        #    invisibly.
2701 224 storres
        if debug:
2702 224 storres
            matrixToReduce = slz_compute_initial_lattice_matrix(intIntP,
2703 224 storres
                                                                alpha,
2704 224 storres
                                                                N,
2705 224 storres
                                                                iBound,
2706 224 storres
                                                                tBound)
2707 224 storres
            maxNorm     = 0
2708 224 storres
            latticeSize = 0
2709 224 storres
            matrixFile = file('/tmp/matrixToReduce.txt', 'w')
2710 224 storres
            for row in matrixToReduce.rows():
2711 224 storres
                currentNorm = row.norm()
2712 224 storres
                if currentNorm > maxNorm:
2713 224 storres
                    maxNorm = currentNorm
2714 224 storres
                latticeSize += 1
2715 224 storres
                for elem in row:
2716 224 storres
                    matrixFile.write(elem.str(base=2) + ",")
2717 224 storres
                matrixFile.write("\n")
2718 224 storres
            #matrixFile.write(matrixToReduce.str(radix="2") + "\n")
2719 224 storres
            matrixFile.close()
2720 224 storres
            #### We use here binary length as defined in LLL princepts.
2721 224 storres
            binaryLength = latticeSize * log(maxNorm)
2722 224 storres
            print "Binary length:", binaryLength.n()
2723 224 storres
            raise Exception("Deliberate stop here.")
2724 224 storres
        # End if debug
2725 219 storres
        reductionTime                     = cputime()
2726 219 storres
        #### Compute the reduced polynomials.
2727 219 storres
        ccReducedPolynomialsList =  \
2728 219 storres
                slz_compute_coppersmith_reduced_polynomials(intIntP,
2729 219 storres
                                                            alpha,
2730 219 storres
                                                            N,
2731 219 storres
                                                            iBound,
2732 219 storres
                                                            tBound)
2733 219 storres
        if ccReducedPolynomialsList is None:
2734 219 storres
            raise Exception("Reduction failed.")
2735 219 storres
        reductionsFullTime    += cputime(reductionTime)
2736 219 storres
        reductionsCount       += 1
2737 219 storres
        if len(ccReducedPolynomialsList) < 2:
2738 219 storres
            print "Nothing to form resultants with."
2739 219 storres
            print
2740 219 storres
            coppCondFailedCount += 1
2741 219 storres
            coppCondFailed = True
2742 219 storres
            ##### Apply a different shrink factor according to
2743 219 storres
            #  the number of compliant polynomials.
2744 219 storres
            if len(ccReducedPolynomialsList) == 0:
2745 219 storres
                ub = lb + bw * noCoppersmithIntervalShrink
2746 219 storres
            else: # At least one compliant polynomial.
2747 219 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
2748 219 storres
            if ub > sdub:
2749 219 storres
                ub = sdub
2750 219 storres
            if lb == ub:
2751 219 storres
                raise Exception("Cant shrink interval \
2752 219 storres
                anymore to get Coppersmith condition.")
2753 219 storres
            nbw = 0
2754 219 storres
            continue
2755 219 storres
        #### We have at least two polynomials.
2756 219 storres
        #    Let us try to compute resultants.
2757 219 storres
        #    For each resultant computed, go for the solutions.
2758 219 storres
        ##### Build the pairs list.
2759 219 storres
        polyPairsList           = []
2760 219 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
2761 219 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
2762 219 storres
                                         len(ccReducedPolynomialsList)):
2763 219 storres
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
2764 219 storres
                                      ccReducedPolynomialsList[polyInnerIndex]))
2765 219 storres
        #### Actual root search.
2766 219 storres
        iRootsSet           = set()
2767 219 storres
        hasNonNullResultant = False
2768 219 storres
        for polyPair in polyPairsList:
2769 219 storres
            resultantsComputationTime   = cputime()
2770 219 storres
            currentResultantI = \
2771 219 storres
                slz_resultant(polyPair[0],
2772 219 storres
                              polyPair[1],
2773 219 storres
                              t)
2774 219 storres
            resultantsComputationsCount    += 1
2775 219 storres
            resultantsComputationsFullTime +=  \
2776 219 storres
                cputime(resultantsComputationTime)
2777 219 storres
            #### Function slz_resultant returns None both for None and O
2778 219 storres
            #    resultants.
2779 219 storres
            if currentResultantI is None:
2780 219 storres
                print "Nul resultant"
2781 219 storres
                continue # Next polyPair.
2782 219 storres
            ## We deleted the currentResultantI computation.
2783 219 storres
            #### We have a non null resultant. From now on, whatever this
2784 219 storres
            #    root search yields, no extra root search is necessary.
2785 219 storres
            hasNonNullResultant = True
2786 219 storres
            #### A constant resultant leads to no root. Root search is done.
2787 219 storres
            if currentResultantI.degree() < 1:
2788 219 storres
                print "Resultant is constant:", currentResultantI
2789 219 storres
                break # There is no root.
2790 219 storres
            #### Actual iroots computation.
2791 219 storres
            rootsComputationTime        = cputime()
2792 219 storres
            iRootsList = Zi(currentResultantI).roots()
2793 219 storres
            rootsComputationsCount      +=  1
2794 219 storres
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
2795 219 storres
            if len(iRootsList) == 0:
2796 219 storres
                print "No roots in \"i\"."
2797 219 storres
                break # No roots in i.
2798 219 storres
            else:
2799 219 storres
                for iRoot in iRootsList:
2800 219 storres
                    # A root is given as a (value, multiplicity) tuple.
2801 219 storres
                    iRootsSet.add(iRoot[0])
2802 219 storres
        # End loop for polyPair in polyParsList. We only loop again if a
2803 219 storres
        # None or zero resultant is found.
2804 219 storres
        #### Prepare for results for the current interval..
2805 219 storres
        intervalResultsList = []
2806 219 storres
        intervalResultsList.append((lb, ub))
2807 219 storres
        #### Check roots.
2808 219 storres
        rootsResultsList = []
2809 219 storres
        for iRoot in iRootsSet:
2810 219 storres
            specificRootResultsList = []
2811 219 storres
            failingBounds           = []
2812 219 storres
            # Root qualifies for modular equation, test it for hardness to round.
2813 219 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + iRoot) / toIntegerFactor)
2814 219 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
2815 219 storres
            #print scalingFunction
2816 219 storres
            scaledHardToRoundCaseAsFloat = \
2817 219 storres
                scalingFunction(hardToRoundCaseAsFloat)
2818 219 storres
            print "Candidate HTRNc at x =", \
2819 219 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
2820 219 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
2821 219 storres
                           function,
2822 219 storres
                           2^-(targetHardnessToRound),
2823 219 storres
                           RRR):
2824 219 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
2825 219 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
2826 219 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
2827 219 storres
                    print "Found in interval."
2828 219 storres
                else:
2829 219 storres
                    print "Found out of interval."
2830 219 storres
                # Check the i root is within the i bound.
2831 219 storres
                if abs(iRoot) > iBound:
2832 219 storres
                    print "IRoot", iRoot, "is out of bounds for modular equation."
2833 219 storres
                    print "i bound:", iBound
2834 219 storres
                    failingBounds.append('i')
2835 219 storres
                    failingBounds.append(iRoot)
2836 219 storres
                    failingBounds.append(iBound)
2837 219 storres
                if len(failingBounds) > 0:
2838 219 storres
                    specificRootResultsList.append(failingBounds)
2839 219 storres
            else: # From slz_is_htrn...
2840 219 storres
                print "is not an HTRN case."
2841 219 storres
            if len(specificRootResultsList) > 0:
2842 219 storres
                rootsResultsList.append(specificRootResultsList)
2843 219 storres
        if len(rootsResultsList) > 0:
2844 219 storres
            intervalResultsList.append(rootsResultsList)
2845 219 storres
        ### Check if a non null resultant was found. If not shrink the interval.
2846 219 storres
        if not hasNonNullResultant:
2847 219 storres
            print "Only null resultants for this reduction, shrinking interval."
2848 219 storres
            resultCondFailed      =  True
2849 219 storres
            resultCondFailedCount += 1
2850 219 storres
            ### Shrink interval for next iteration.
2851 219 storres
            ub = lb + bw * onlyNullResultantsShrink
2852 219 storres
            if ub > sdub:
2853 219 storres
                ub = sdub
2854 219 storres
            nbw = 0
2855 219 storres
            continue
2856 219 storres
        #### An intervalResultsList has at least the bounds.
2857 219 storres
        globalResultsList.append(intervalResultsList)
2858 219 storres
        #### Compute an incremented width for next upper bound, only
2859 219 storres
        #    if not Coppersmith condition nor resultant condition
2860 219 storres
        #    failed at the previous run.
2861 219 storres
        if not coppCondFailed and not resultCondFailed:
2862 219 storres
            nbw = noErrorIntervalStretch * bw
2863 219 storres
        else:
2864 219 storres
            nbw = bw
2865 219 storres
        ##### Reset the failure flags. They will be raised
2866 219 storres
        #     again if needed.
2867 219 storres
        coppCondFailed   = False
2868 219 storres
        resultCondFailed = False
2869 219 storres
        #### For next iteration (at end of loop)
2870 219 storres
        #print "nbw:", nbw
2871 219 storres
        lb  = ub
2872 219 storres
        ub += nbw
2873 219 storres
        if ub > sdub:
2874 219 storres
            ub = sdub
2875 219 storres
        print
2876 219 storres
    # End while True
2877 219 storres
    ## Main loop just ended.
2878 219 storres
    globalWallTime = walltime(wallTimeStart)
2879 219 storres
    globalCpuTime  = cputime(cpuTimeStart)
2880 219 storres
    ## Output results
2881 219 storres
    print ; print "Intervals and HTRNs" ; print
2882 219 storres
    for intervalResultsList in globalResultsList:
2883 222 storres
        intervalResultString = "[" + str(intervalResultsList[0][0]) +\
2884 222 storres
                               "," + str(intervalResultsList[0][1])  + "]"
2885 222 storres
        print intervalResultString,
2886 219 storres
        if len(intervalResultsList) > 1:
2887 219 storres
            rootsResultsList = intervalResultsList[1]
2888 222 storres
            specificRootResultIndex = 0
2889 219 storres
            for specificRootResultsList in rootsResultsList:
2890 222 storres
                if specificRootResultIndex == 0:
2891 222 storres
                    print "\t", specificRootResultsList[0],
2892 222 storres
                else:
2893 222 storres
                    print " " * len(intervalResultString), "\t", \
2894 222 storres
                          specificRootResultsList[0],
2895 219 storres
                if len(specificRootResultsList) > 1:
2896 222 storres
                    print specificRootResultsList[1]
2897 222 storres
                specificRootResultIndex += 1
2898 219 storres
        print ; print
2899 219 storres
    #print globalResultsList
2900 219 storres
    #
2901 219 storres
    print "Timers and counters"
2902 219 storres
    print
2903 219 storres
    print "Number of iterations:", iterCount
2904 219 storres
    print "Taylor condition failures:", taylCondFailedCount
2905 219 storres
    print "Coppersmith condition failures:", coppCondFailedCount
2906 219 storres
    print "Resultant condition failures:", resultCondFailedCount
2907 219 storres
    print "Iterations count: ", iterCount
2908 219 storres
    print "Number of intervals:", len(globalResultsList)
2909 219 storres
    print "Number of basis constructions:", basisConstructionsCount
2910 219 storres
    print "Total CPU time spent in basis constructions:", \
2911 219 storres
        basisConstructionsFullTime
2912 219 storres
    if basisConstructionsCount != 0:
2913 219 storres
        print "Average basis construction CPU time:", \
2914 219 storres
            basisConstructionsFullTime/basisConstructionsCount
2915 219 storres
    print "Number of reductions:", reductionsCount
2916 219 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
2917 219 storres
    if reductionsCount != 0:
2918 219 storres
        print "Average reduction CPU time:", \
2919 219 storres
            reductionsFullTime/reductionsCount
2920 219 storres
    print "Number of resultants computation rounds:", \
2921 219 storres
        resultantsComputationsCount
2922 219 storres
    print "Total CPU time spent in resultants computation rounds:", \
2923 219 storres
        resultantsComputationsFullTime
2924 219 storres
    if resultantsComputationsCount != 0:
2925 219 storres
        print "Average resultants computation round CPU time:", \
2926 219 storres
            resultantsComputationsFullTime/resultantsComputationsCount
2927 219 storres
    print "Number of root finding rounds:", rootsComputationsCount
2928 219 storres
    print "Total CPU time spent in roots finding rounds:", \
2929 219 storres
        rootsComputationsFullTime
2930 219 storres
    if rootsComputationsCount != 0:
2931 219 storres
        print "Average roots finding round CPU time:", \
2932 219 storres
            rootsComputationsFullTime/rootsComputationsCount
2933 219 storres
    print "Global Wall time:", globalWallTime
2934 219 storres
    print "Global CPU time:", globalCpuTime
2935 219 storres
    ## Output counters
2936 219 storres
# End srs_runSLZ-v05
2937 222 storres
2938 222 storres
def srs_run_SLZ_v06(inputFunction,
2939 222 storres
                    inputLowerBound,
2940 222 storres
                    inputUpperBound,
2941 222 storres
                    alpha,
2942 222 storres
                    degree,
2943 222 storres
                    precision,
2944 222 storres
                    emin,
2945 222 storres
                    emax,
2946 222 storres
                    targetHardnessToRound,
2947 222 storres
                    debug = True):
2948 222 storres
    """
2949 222 storres
    Changes from V5:
2950 222 storres
        Very verbose
2951 222 storres
    Changes from V4:
2952 222 storres
        Approximation polynomial has coefficients rounded.
2953 222 storres
    Changes from V3:
2954 222 storres
        Root search is changed again:
2955 222 storres
            - only resultants in i are computed;
2956 222 storres
            - roots in i are searched for;
2957 222 storres
            - if any, they are tested for hardness-to-round.
2958 222 storres
    Changes from V2:
2959 222 storres
        Root search is changed:
2960 222 storres
            - we compute the resultants in i and in t;
2961 222 storres
            - we compute the roots set of each of these resultants;
2962 222 storres
            - we combine all the possible pairs between the two sets;
2963 222 storres
            - we check these pairs in polynomials for correctness.
2964 222 storres
    Changes from V1:
2965 222 storres
        1- check for roots as soon as a resultant is computed;
2966 222 storres
        2- once a non null resultant is found, check for roots;
2967 222 storres
        3- constant resultant == no root.
2968 222 storres
    """
2969 222 storres
    if debug:
2970 222 storres
        print "Function                :", inputFunction
2971 222 storres
        print "Lower bound             :", inputLowerBound
2972 222 storres
        print "Upper bounds            :", inputUpperBound
2973 222 storres
        print "Alpha                   :", alpha
2974 222 storres
        print "Degree                  :", degree
2975 222 storres
        print "Precision               :", precision
2976 222 storres
        print "Emin                    :", emin
2977 222 storres
        print "Emax                    :", emax
2978 222 storres
        print "Target hardness-to-round:", targetHardnessToRound
2979 222 storres
        print
2980 222 storres
    ## Important constants.
2981 222 storres
    ### Stretch the interval if no error happens.
2982 222 storres
    noErrorIntervalStretch = 1 + 2^(-5)
2983 222 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
2984 222 storres
    #   by the following factor.
2985 222 storres
    noCoppersmithIntervalShrink = 1/2
2986 222 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
2987 222 storres
    #   shrink the interval by the following factor.
2988 222 storres
    oneCoppersmithIntervalShrink = 3/4
2989 222 storres
    #### If only null resultants are found, shrink the interval by the
2990 222 storres
    #    following factor.
2991 222 storres
    onlyNullResultantsShrink     = 3/4
2992 222 storres
    ## Structures.
2993 222 storres
    RRR         = RealField(precision)
2994 222 storres
    RRIF        = RealIntervalField(precision)
2995 222 storres
    ## Converting input bound into the "right" field.
2996 222 storres
    lowerBound = RRR(inputLowerBound)
2997 222 storres
    upperBound = RRR(inputUpperBound)
2998 222 storres
    ## Before going any further, check domain and image binade conditions.
2999 222 storres
    print inputFunction(1).n()
3000 222 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
3001 222 storres
    if output is None:
3002 222 storres
        print "Invalid domain/image binades. Domain:",\
3003 222 storres
        lowerBound, upperBound, "Images:", \
3004 222 storres
        inputFunction(lowerBound), inputFunction(upperBound)
3005 222 storres
        raise Exception("Invalid domain/image binades.")
3006 222 storres
    lb = output[0] ; ub = output[1]
3007 222 storres
    if lb != lowerBound or ub != upperBound:
3008 222 storres
        print "lb:", lb, " - ub:", ub
3009 222 storres
        print "Invalid domain/image binades. Domain:",\
3010 222 storres
        lowerBound, upperBound, "Images:", \
3011 222 storres
        inputFunction(lowerBound), inputFunction(upperBound)
3012 222 storres
        raise Exception("Invalid domain/image binades.")
3013 222 storres
    #
3014 222 storres
    ## Progam initialization
3015 222 storres
    ### Approximation polynomial accuracy and hardness to round.
3016 222 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
3017 222 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
3018 222 storres
    ### Significand to integer conversion ratio.
3019 222 storres
    toIntegerFactor           = 2^(precision-1)
3020 222 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
3021 222 storres
    ### Variables and rings for polynomials and root searching.
3022 222 storres
    i=var('i')
3023 222 storres
    t=var('t')
3024 222 storres
    inputFunctionVariable = inputFunction.variables()[0]
3025 222 storres
    function = inputFunction.subs({inputFunctionVariable:i})
3026 222 storres
    #  Polynomial Rings over the integers, for root finding.
3027 222 storres
    Zi = ZZ[i]
3028 222 storres
    ## Number of iterations limit.
3029 222 storres
    maxIter = 100000
3030 222 storres
    #
3031 222 storres
    ## Compute the scaled function and the degree, in their Sollya version
3032 222 storres
    #  once for all.
3033 222 storres
    (scaledf, sdlb, sdub, silb, siub) = \
3034 222 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
3035 222 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
3036 222 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
3037 222 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
3038 222 storres
    #
3039 222 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
3040 222 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
3041 222 storres
    (unscalingFunction, scalingFunction) = \
3042 222 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
3043 222 storres
    #print scalingFunction, unscalingFunction
3044 222 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
3045 222 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
3046 222 storres
    if internalSollyaPrec < 192:
3047 222 storres
        internalSollyaPrec = 192
3048 227 storres
    pobyso_lib_init()
3049 222 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
3050 222 storres
    print "Sollya internal precision:", internalSollyaPrec
3051 222 storres
    targetPlusOnePrecRF       = RealField(RRR.prec()+1)
3052 222 storres
    if internalSollyaPrec < 1024:
3053 222 storres
        quasiExactRF              = RealField(1014)
3054 222 storres
    else:
3055 222 storres
        quasiExactRF              = RealField(internalSollyaPrec)
3056 222 storres
    ## Some variables.
3057 222 storres
    ### General variables
3058 222 storres
    lb                  = sdlb
3059 222 storres
    ub                  = sdub
3060 222 storres
    nbw                 = 0
3061 222 storres
    intervalUlp         = ub.ulp()
3062 222 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
3063 222 storres
    ic                  = 0
3064 222 storres
    icAsInt             = 0    # Set from ic.
3065 222 storres
    solutionsSet        = set()
3066 222 storres
    tsErrorWidth        = []
3067 222 storres
    csErrorVectors      = []
3068 222 storres
    csVectorsResultants = []
3069 222 storres
    floatP              = 0  # Taylor polynomial.
3070 222 storres
    floatPcv            = 0  # Ditto with variable change.
3071 222 storres
    intvl               = "" # Taylor interval
3072 222 storres
    terr                = 0  # Taylor error.
3073 222 storres
    iterCount = 0
3074 222 storres
    htrnSet = set()
3075 222 storres
    ### Timers and counters.
3076 222 storres
    wallTimeStart                   = 0
3077 222 storres
    cpuTimeStart                    = 0
3078 222 storres
    taylCondFailedCount             = 0
3079 222 storres
    coppCondFailedCount             = 0
3080 222 storres
    resultCondFailedCount           = 0
3081 222 storres
    coppCondFailed                  = False
3082 222 storres
    resultCondFailed                = False
3083 222 storres
    globalResultsList               = []
3084 222 storres
    basisConstructionsCount         = 0
3085 222 storres
    basisConstructionsFullTime      = 0
3086 222 storres
    basisConstructionTime           = 0
3087 222 storres
    reductionsCount                 = 0
3088 222 storres
    reductionsFullTime              = 0
3089 222 storres
    reductionTime                   = 0
3090 222 storres
    resultantsComputationsCount     = 0
3091 222 storres
    resultantsComputationsFullTime  = 0
3092 222 storres
    resultantsComputationTime       = 0
3093 222 storres
    rootsComputationsCount          = 0
3094 222 storres
    rootsComputationsFullTime       = 0
3095 222 storres
    rootsComputationTime            = 0
3096 222 storres
    print
3097 222 storres
    ## Global times are started here.
3098 222 storres
    wallTimeStart                   = walltime()
3099 222 storres
    cpuTimeStart                    = cputime()
3100 222 storres
    ## Main loop.
3101 222 storres
    while True:
3102 222 storres
        if lb >= sdub:
3103 222 storres
            print "Lower bound reached upper bound."
3104 222 storres
            break
3105 222 storres
        if iterCount == maxIter:
3106 222 storres
            print "Reached maxIter. Aborting"
3107 222 storres
            break
3108 222 storres
        iterCount += 1
3109 222 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
3110 222 storres
            "log2(numbers)."
3111 227 storres
        #print "Debugging..."
3112 222 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
3113 227 storres
        prceSo = slz_compute_polynomial_and_interval_02(scaledfSo,
3114 222 storres
                                                        degreeSo,
3115 222 storres
                                                        lb,
3116 222 storres
                                                        ub,
3117 222 storres
                                                        polyApproxAccur,
3118 222 storres
                                                        debug=True)
3119 222 storres
        if debug:
3120 227 storres
            print "Sollya Taylor polynomial:", ; pobyso_autoprint(prceSo[0])
3121 227 storres
            print "Sollya interval         :", ; pobyso_autoprint(prceSo[1])
3122 227 storres
            print "Sollya interval center  :", ; pobyso_autoprint(prceSo[2])
3123 227 storres
            print "Sollya Taylor error     :", ; pobyso_autoprint(prceSo[3])
3124 222 storres
3125 222 storres
        ### Convert back the data into Sage space.
3126 222 storres
        (floatP, floatPcv, intvl, ic, terr) = \
3127 222 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
3128 222 storres
                                                 prceSo[1], prceSo[2],
3129 222 storres
                                                 prceSo[3]))
3130 228 storres
        print "Sage Taylor polynomial:", floatP, floatP.parent()
3131 228 storres
        floatPcoeffs = floatP.coefficients()
3132 228 storres
        for coeff in floatPcoeffs:
3133 228 storres
            print coeff.n(prec=coeff.parent().prec()).str(base=2)
3134 228 storres
            print coeff.n(prec=coeff.parent().prec())
3135 222 storres
        intvl = RRIF(intvl)
3136 222 storres
        ## Clean-up Sollya stuff.
3137 222 storres
        for elem in prceSo:
3138 222 storres
            sollya_lib_clear_obj(elem)
3139 222 storres
        #print  floatP, floatPcv, intvl, ic, terr
3140 222 storres
        #print floatP
3141 222 storres
        #print intvl.endpoints()[0].n(), \
3142 222 storres
        #      ic.n(),
3143 222 storres
        #intvl.endpoints()[1].n()
3144 222 storres
        ### Check returned data.
3145 222 storres
        #### Is approximation error OK?
3146 222 storres
        if terr > polyApproxAccur:
3147 222 storres
            exceptionErrorMess  = \
3148 222 storres
                "Approximation failed - computed error:" + \
3149 222 storres
                str(terr) + " - target error: "
3150 222 storres
            exceptionErrorMess += \
3151 222 storres
                str(polyApproxAccur) + ". Aborting!"
3152 222 storres
            raise Exception(exceptionErrorMess)
3153 222 storres
        #### Is lower bound OK?
3154 222 storres
        if lb != intvl.endpoints()[0]:
3155 222 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
3156 222 storres
                               str(lb) + ". Aborting!"
3157 222 storres
            raise Exception(exceptionErrorMess)
3158 222 storres
        #### Set upper bound.
3159 222 storres
        if ub > intvl.endpoints()[1]:
3160 222 storres
            ub = intvl.endpoints()[1]
3161 222 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
3162 222 storres
            "log2(numbers)."
3163 222 storres
            taylCondFailedCount += 1
3164 222 storres
        #### Is interval not degenerate?
3165 222 storres
        if lb >= ub:
3166 222 storres
            exceptionErrorMess = "Degenerate interval: " + \
3167 222 storres
                                "lowerBound(" + str(lb) +\
3168 222 storres
                                ")>= upperBound(" + str(ub) + \
3169 222 storres
                                "). Aborting!"
3170 222 storres
            raise Exception(exceptionErrorMess)
3171 222 storres
        #### Is interval center ok?
3172 222 storres
        if ic <= lb or ic >= ub:
3173 222 storres
            exceptionErrorMess =  "Invalid interval center for " + \
3174 222 storres
                                str(lb) + ',' + str(ic) + ',' +  \
3175 222 storres
                                str(ub) + ". Aborting!"
3176 222 storres
            raise Exception(exceptionErrorMess)
3177 222 storres
        ##### Current interval width and reset future interval width.
3178 222 storres
        bw = ub - lb
3179 222 storres
        nbw = 0
3180 222 storres
        icAsInt = int(ic * toIntegerFactor)
3181 222 storres
        #### The following ratio is always >= 1. In case we may want to
3182 222 storres
        #    enlarge the interval
3183 222 storres
        curTaylErrRat = polyApproxAccur / terr
3184 222 storres
        ### Make the  integral transformations.
3185 222 storres
        #### Bounds and interval center.
3186 222 storres
        intIc = int(ic * toIntegerFactor)
3187 222 storres
        intLb = int(lb * toIntegerFactor) - intIc
3188 222 storres
        intUb = int(ub * toIntegerFactor) - intIc
3189 222 storres
        #
3190 222 storres
        #### Polynomials
3191 222 storres
        basisConstructionTime         = cputime()
3192 222 storres
        ##### To a polynomial with rational coefficients with rational arguments
3193 222 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
3194 222 storres
        if debug:
3195 222 storres
            print "Polynomial: rational coefficients for rational argument:"
3196 222 storres
            print ratRatP
3197 222 storres
        ##### To a polynomial with rational coefficients with integer arguments
3198 222 storres
        ratIntP = \
3199 222 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
3200 222 storres
        if debug:
3201 222 storres
            print "Polynomial: rational coefficients for integer argument:"
3202 222 storres
            print ratIntP
3203 222 storres
        #####  Ultimately a multivariate polynomial with integer coefficients
3204 222 storres
        #      with integer arguments.
3205 222 storres
        coppersmithTuple = \
3206 222 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
3207 222 storres
                                                        precision,
3208 222 storres
                                                        targetHardnessToRound,
3209 222 storres
                                                        i, t)
3210 222 storres
        #### Recover Coppersmith information.
3211 222 storres
        intIntP = coppersmithTuple[0]
3212 222 storres
        N = coppersmithTuple[1]
3213 222 storres
        nAtAlpha = N^alpha
3214 222 storres
        tBound = coppersmithTuple[2]
3215 222 storres
        leastCommonMultiple = coppersmithTuple[3]
3216 222 storres
        iBound = max(abs(intLb),abs(intUb))
3217 222 storres
        if debug:
3218 222 storres
            print "Polynomial: integer coefficients for integer argument:"
3219 222 storres
            print intIntP
3220 222 storres
            print "N:", N
3221 222 storres
            print "t bound:", tBound
3222 222 storres
            print "i bound:", iBound
3223 222 storres
            print "Least common multiple:", leastCommonMultiple
3224 222 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
3225 222 storres
        basisConstructionsCount           += 1
3226 228 storres
3227 222 storres
        #### Compute the matrix to reduce.
3228 222 storres
        matrixToReduce = slz_compute_initial_lattice_matrix(intIntP,
3229 222 storres
                                                            alpha,
3230 222 storres
                                                            N,
3231 222 storres
                                                            iBound,
3232 228 storres
                                                            tBound,
3233 228 storres
                                                            True)
3234 222 storres
        matrixFile = file('/tmp/matrixToReduce.txt', 'w')
3235 222 storres
        for row in matrixToReduce.rows():
3236 222 storres
            matrixFile.write(str(row) + "\n")
3237 222 storres
        matrixFile.close()
3238 228 storres
        #raise Exception("Deliberate stop here.")
3239 228 storres
3240 222 storres
        reductionTime                     = cputime()
3241 222 storres
        #### Compute the reduced polynomials.
3242 222 storres
        ccReducedPolynomialsList =  \
3243 222 storres
                slz_compute_coppersmith_reduced_polynomials(intIntP,
3244 222 storres
                                                            alpha,
3245 222 storres
                                                            N,
3246 222 storres
                                                            iBound,
3247 222 storres
                                                            tBound)
3248 222 storres
        if ccReducedPolynomialsList is None:
3249 222 storres
            raise Exception("Reduction failed.")
3250 222 storres
        reductionsFullTime    += cputime(reductionTime)
3251 222 storres
        reductionsCount       += 1
3252 222 storres
        if len(ccReducedPolynomialsList) < 2:
3253 222 storres
            print "Nothing to form resultants with."
3254 222 storres
            print
3255 222 storres
            coppCondFailedCount += 1
3256 222 storres
            coppCondFailed = True
3257 222 storres
            ##### Apply a different shrink factor according to
3258 222 storres
            #  the number of compliant polynomials.
3259 222 storres
            if len(ccReducedPolynomialsList) == 0:
3260 222 storres
                ub = lb + bw * noCoppersmithIntervalShrink
3261 222 storres
            else: # At least one compliant polynomial.
3262 222 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
3263 222 storres
            if ub > sdub:
3264 222 storres
                ub = sdub
3265 222 storres
            if lb == ub:
3266 222 storres
                raise Exception("Cant shrink interval \
3267 222 storres
                anymore to get Coppersmith condition.")
3268 222 storres
            nbw = 0
3269 222 storres
            continue
3270 222 storres
        #### We have at least two polynomials.
3271 222 storres
        #    Let us try to compute resultants.
3272 222 storres
        #    For each resultant computed, go for the solutions.
3273 222 storres
        ##### Build the pairs list.
3274 222 storres
        polyPairsList           = []
3275 222 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
3276 222 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
3277 222 storres
                                         len(ccReducedPolynomialsList)):
3278 222 storres
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
3279 222 storres
                                      ccReducedPolynomialsList[polyInnerIndex]))
3280 222 storres
        #### Actual root search.
3281 222 storres
        iRootsSet           = set()
3282 222 storres
        hasNonNullResultant = False
3283 222 storres
        for polyPair in polyPairsList:
3284 222 storres
            resultantsComputationTime   = cputime()
3285 222 storres
            currentResultantI = \
3286 222 storres
                slz_resultant(polyPair[0],
3287 222 storres
                              polyPair[1],
3288 222 storres
                              t)
3289 222 storres
            resultantsComputationsCount    += 1
3290 222 storres
            resultantsComputationsFullTime +=  \
3291 222 storres
                cputime(resultantsComputationTime)
3292 222 storres
            #### Function slz_resultant returns None both for None and O
3293 222 storres
            #    resultants.
3294 222 storres
            if currentResultantI is None:
3295 222 storres
                print "Nul resultant"
3296 222 storres
                continue # Next polyPair.
3297 222 storres
            ## We deleted the currentResultantI computation.
3298 222 storres
            #### We have a non null resultant. From now on, whatever this
3299 222 storres
            #    root search yields, no extra root search is necessary.
3300 222 storres
            hasNonNullResultant = True
3301 222 storres
            #### A constant resultant leads to no root. Root search is done.
3302 222 storres
            if currentResultantI.degree() < 1:
3303 222 storres
                print "Resultant is constant:", currentResultantI
3304 222 storres
                break # There is no root.
3305 222 storres
            #### Actual iroots computation.
3306 222 storres
            rootsComputationTime        = cputime()
3307 222 storres
            iRootsList = Zi(currentResultantI).roots()
3308 222 storres
            rootsComputationsCount      +=  1
3309 222 storres
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
3310 222 storres
            if len(iRootsList) == 0:
3311 222 storres
                print "No roots in \"i\"."
3312 222 storres
                break # No roots in i.
3313 222 storres
            else:
3314 222 storres
                for iRoot in iRootsList:
3315 222 storres
                    # A root is given as a (value, multiplicity) tuple.
3316 222 storres
                    iRootsSet.add(iRoot[0])
3317 222 storres
        # End loop for polyPair in polyParsList. We only loop again if a
3318 222 storres
        # None or zero resultant is found.
3319 222 storres
        #### Prepare for results for the current interval..
3320 222 storres
        intervalResultsList = []
3321 222 storres
        intervalResultsList.append((lb, ub))
3322 222 storres
        #### Check roots.
3323 222 storres
        rootsResultsList = []
3324 222 storres
        for iRoot in iRootsSet:
3325 222 storres
            specificRootResultsList = []
3326 222 storres
            failingBounds           = []
3327 222 storres
            # Root qualifies for modular equation, test it for hardness to round.
3328 222 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + iRoot) / toIntegerFactor)
3329 222 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
3330 222 storres
            #print scalingFunction
3331 222 storres
            scaledHardToRoundCaseAsFloat = \
3332 222 storres
                scalingFunction(hardToRoundCaseAsFloat)
3333 222 storres
            print "Candidate HTRNc at x =", \
3334 222 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
3335 222 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
3336 222 storres
                           function,
3337 222 storres
                           2^-(targetHardnessToRound),
3338 222 storres
                           RRR,
3339 222 storres
                           targetPlusOnePrecRF,
3340 222 storres
                           quasiExactRF):
3341 222 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
3342 222 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
3343 222 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
3344 222 storres
                    print "Found in interval."
3345 222 storres
                else:
3346 222 storres
                    print "Found out of interval."
3347 222 storres
                # Check the i root is within the i bound.
3348 222 storres
                if abs(iRoot) > iBound:
3349 222 storres
                    print "IRoot", iRoot, "is out of bounds for modular equation."
3350 222 storres
                    print "i bound:", iBound
3351 222 storres
                    failingBounds.append('i')
3352 222 storres
                    failingBounds.append(iRoot)
3353 222 storres
                    failingBounds.append(iBound)
3354 222 storres
                if len(failingBounds) > 0:
3355 222 storres
                    specificRootResultsList.append(failingBounds)
3356 222 storres
            else: # From slz_is_htrn...
3357 222 storres
                print "is not an HTRN case."
3358 222 storres
            if len(specificRootResultsList) > 0:
3359 222 storres
                rootsResultsList.append(specificRootResultsList)
3360 222 storres
        if len(rootsResultsList) > 0:
3361 222 storres
            intervalResultsList.append(rootsResultsList)
3362 222 storres
        ### Check if a non null resultant was found. If not shrink the interval.
3363 222 storres
        if not hasNonNullResultant:
3364 222 storres
            print "Only null resultants for this reduction, shrinking interval."
3365 222 storres
            resultCondFailed      =  True
3366 222 storres
            resultCondFailedCount += 1
3367 222 storres
            ### Shrink interval for next iteration.
3368 222 storres
            ub = lb + bw * onlyNullResultantsShrink
3369 222 storres
            if ub > sdub:
3370 222 storres
                ub = sdub
3371 222 storres
            nbw = 0
3372 222 storres
            continue
3373 222 storres
        #### An intervalResultsList has at least the bounds.
3374 222 storres
        globalResultsList.append(intervalResultsList)
3375 222 storres
        #### Compute an incremented width for next upper bound, only
3376 222 storres
        #    if not Coppersmith condition nor resultant condition
3377 222 storres
        #    failed at the previous run.
3378 222 storres
        if not coppCondFailed and not resultCondFailed:
3379 222 storres
            nbw = noErrorIntervalStretch * bw
3380 222 storres
        else:
3381 222 storres
            nbw = bw
3382 222 storres
        ##### Reset the failure flags. They will be raised
3383 222 storres
        #     again if needed.
3384 222 storres
        coppCondFailed   = False
3385 222 storres
        resultCondFailed = False
3386 222 storres
        #### For next iteration (at end of loop)
3387 222 storres
        #print "nbw:", nbw
3388 222 storres
        lb  = ub
3389 222 storres
        ub += nbw
3390 222 storres
        if ub > sdub:
3391 222 storres
            ub = sdub
3392 222 storres
        print
3393 222 storres
    # End while True
3394 222 storres
    ## Main loop just ended.
3395 222 storres
    globalWallTime = walltime(wallTimeStart)
3396 222 storres
    globalCpuTime  = cputime(cpuTimeStart)
3397 222 storres
    ## Output results
3398 222 storres
    print ; print "Intervals and HTRNs" ; print
3399 222 storres
    for intervalResultsList in globalResultsList:
3400 222 storres
        intervalResultString = "[" + str(intervalResultsList[0][0]) +\
3401 222 storres
                               "," + str(intervalResultsList[0][1])  + "]"
3402 222 storres
        print intervalResultString,
3403 222 storres
        if len(intervalResultsList) > 1:
3404 222 storres
            rootsResultsList = intervalResultsList[1]
3405 222 storres
            specificRootResultIndex = 0
3406 222 storres
            for specificRootResultsList in rootsResultsList:
3407 222 storres
                if specificRootResultIndex == 0:
3408 222 storres
                    print "\t", specificRootResultsList[0],
3409 222 storres
                else:
3410 222 storres
                    print " " * len(intervalResultString), "\t", \
3411 222 storres
                          specificRootResultsList[0],
3412 222 storres
                if len(specificRootResultsList) > 1:
3413 222 storres
                    print specificRootResultsList[1]
3414 222 storres
                specificRootResultIndex += 1
3415 222 storres
        print ; print
3416 222 storres
    #print globalResultsList
3417 222 storres
    #
3418 222 storres
    print "Timers and counters"
3419 222 storres
    print
3420 222 storres
    print "Number of iterations:", iterCount
3421 222 storres
    print "Taylor condition failures:", taylCondFailedCount
3422 222 storres
    print "Coppersmith condition failures:", coppCondFailedCount
3423 222 storres
    print "Resultant condition failures:", resultCondFailedCount
3424 222 storres
    print "Iterations count: ", iterCount
3425 222 storres
    print "Number of intervals:", len(globalResultsList)
3426 222 storres
    print "Number of basis constructions:", basisConstructionsCount
3427 222 storres
    print "Total CPU time spent in basis constructions:", \
3428 222 storres
        basisConstructionsFullTime
3429 222 storres
    if basisConstructionsCount != 0:
3430 222 storres
        print "Average basis construction CPU time:", \
3431 222 storres
            basisConstructionsFullTime/basisConstructionsCount
3432 222 storres
    print "Number of reductions:", reductionsCount
3433 222 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
3434 222 storres
    if reductionsCount != 0:
3435 222 storres
        print "Average reduction CPU time:", \
3436 222 storres
            reductionsFullTime/reductionsCount
3437 222 storres
    print "Number of resultants computation rounds:", \
3438 222 storres
        resultantsComputationsCount
3439 222 storres
    print "Total CPU time spent in resultants computation rounds:", \
3440 222 storres
        resultantsComputationsFullTime
3441 222 storres
    if resultantsComputationsCount != 0:
3442 222 storres
        print "Average resultants computation round CPU time:", \
3443 222 storres
            resultantsComputationsFullTime/resultantsComputationsCount
3444 222 storres
    print "Number of root finding rounds:", rootsComputationsCount
3445 222 storres
    print "Total CPU time spent in roots finding rounds:", \
3446 222 storres
        rootsComputationsFullTime
3447 222 storres
    if rootsComputationsCount != 0:
3448 222 storres
        print "Average roots finding round CPU time:", \
3449 222 storres
            rootsComputationsFullTime/rootsComputationsCount
3450 222 storres
    print "Global Wall time:", globalWallTime
3451 222 storres
    print "Global CPU time:", globalCpuTime
3452 222 storres
    ## Output counters
3453 222 storres
# End srs_runSLZ-v06