Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (252,14 ko)

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