Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (107,6 ko)

1 213 storres
r"""
2 213 storres
Main SLZ algorithm body in several versions.
3 213 storres
4 213 storres
AUTHORS:
5 213 storres
- S.T. (2015-10-10): initial version
6 213 storres
7 213 storres
Examples:
8 213 storres
    TODO
9 194 storres
"""
10 213 storres
print "sageRationalOperations loading..."
11 213 storres
12 213 storres
def srs_compute_lattice_volume(inputFunction,
13 213 storres
                    inputLowerBound,
14 213 storres
                    inputUpperBound,
15 213 storres
                    alpha,
16 213 storres
                    degree,
17 213 storres
                    precision,
18 213 storres
                    emin,
19 213 storres
                    emax,
20 213 storres
                    targetHardnessToRound,
21 213 storres
                    debug = False):
22 213 storres
    """
23 213 storres
    Changes from V2:
24 213 storres
        Root search is changed:
25 213 storres
            - we compute the resultants in i and in t;
26 213 storres
            - we compute the roots set of each of these resultants;
27 213 storres
            - we combine all the possible pairs between the two sets;
28 213 storres
            - we check these pairs in polynomials for correctness.
29 213 storres
    Changes from V1:
30 213 storres
        1- check for roots as soon as a resultant is computed;
31 213 storres
        2- once a non null resultant is found, check for roots;
32 213 storres
        3- constant resultant == no root.
33 213 storres
    """
34 213 storres
35 213 storres
    if debug:
36 213 storres
        print "Function                :", inputFunction
37 213 storres
        print "Lower bound             :", inputLowerBound
38 213 storres
        print "Upper bounds            :", inputUpperBound
39 213 storres
        print "Alpha                   :", alpha
40 213 storres
        print "Degree                  :", degree
41 213 storres
        print "Precision               :", precision
42 213 storres
        print "Emin                    :", emin
43 213 storres
        print "Emax                    :", emax
44 213 storres
        print "Target hardness-to-round:", targetHardnessToRound
45 213 storres
        print
46 213 storres
    ## Important constants.
47 213 storres
    ### Stretch the interval if no error happens.
48 213 storres
    noErrorIntervalStretch = 1 + 2^(-5)
49 213 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
50 213 storres
    #   by the following factor.
51 213 storres
    noCoppersmithIntervalShrink = 1/2
52 213 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
53 213 storres
    #   shrink the interval by the following factor.
54 213 storres
    oneCoppersmithIntervalShrink = 3/4
55 213 storres
    #### If only null resultants are found, shrink the interval by the
56 213 storres
    #    following factor.
57 213 storres
    onlyNullResultantsShrink     = 3/4
58 213 storres
    ## Structures.
59 213 storres
    RRR         = RealField(precision)
60 213 storres
    RRIF        = RealIntervalField(precision)
61 213 storres
    ## Converting input bound into the "right" field.
62 213 storres
    lowerBound = RRR(inputLowerBound)
63 213 storres
    upperBound = RRR(inputUpperBound)
64 213 storres
    ## Before going any further, check domain and image binade conditions.
65 213 storres
    print inputFunction(1).n()
66 213 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
67 213 storres
    if output is None:
68 213 storres
        print "Invalid domain/image binades. Domain:",\
69 213 storres
        lowerBound, upperBound, "Images:", \
70 213 storres
        inputFunction(lowerBound), inputFunction(upperBound)
71 213 storres
        raise Exception("Invalid domain/image binades.")
72 213 storres
    lb = output[0] ; ub = output[1]
73 213 storres
    if lb != lowerBound or ub != upperBound:
74 213 storres
        print "lb:", lb, " - ub:", ub
75 213 storres
        print "Invalid domain/image binades. Domain:",\
76 213 storres
        lowerBound, upperBound, "Images:", \
77 213 storres
        inputFunction(lowerBound), inputFunction(upperBound)
78 213 storres
        raise Exception("Invalid domain/image binades.")
79 213 storres
    #
80 213 storres
    ## Progam initialization
81 213 storres
    ### Approximation polynomial accuracy and hardness to round.
82 213 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
83 213 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
84 213 storres
    ### Significand to integer conversion ratio.
85 213 storres
    toIntegerFactor           = 2^(precision-1)
86 213 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
87 213 storres
    ### Variables and rings for polynomials and root searching.
88 213 storres
    i=var('i')
89 213 storres
    t=var('t')
90 213 storres
    inputFunctionVariable = inputFunction.variables()[0]
91 213 storres
    function = inputFunction.subs({inputFunctionVariable:i})
92 213 storres
    #  Polynomial Rings over the integers, for root finding.
93 213 storres
    Zi = ZZ[i]
94 213 storres
    Zt = ZZ[t]
95 213 storres
    Zit = ZZ[i,t]
96 213 storres
    ## Number of iterations limit.
97 213 storres
    maxIter = 100000
98 213 storres
    #
99 213 storres
    ## Compute the scaled function and the degree, in their Sollya version
100 213 storres
    #  once for all.
101 213 storres
    (scaledf, sdlb, sdub, silb, siub) = \
102 213 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
103 213 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
104 213 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
105 213 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
106 213 storres
    #
107 213 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
108 213 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
109 213 storres
    (unscalingFunction, scalingFunction) = \
110 213 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
111 213 storres
    #print scalingFunction, unscalingFunction
112 213 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
113 213 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
114 213 storres
    if internalSollyaPrec < 192:
115 213 storres
        internalSollyaPrec = 192
116 213 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
117 213 storres
    print "Sollya internal precision:", internalSollyaPrec
118 213 storres
    ## Some variables.
119 213 storres
    ### General variables
120 213 storres
    lb                  = sdlb
121 213 storres
    ub                  = sdub
122 213 storres
    nbw                 = 0
123 213 storres
    intervalUlp         = ub.ulp()
124 213 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
125 213 storres
    ic                  = 0
126 213 storres
    icAsInt             = 0    # Set from ic.
127 213 storres
    solutionsSet        = set()
128 213 storres
    tsErrorWidth        = []
129 213 storres
    csErrorVectors      = []
130 213 storres
    csVectorsResultants = []
131 213 storres
    floatP              = 0  # Taylor polynomial.
132 213 storres
    floatPcv            = 0  # Ditto with variable change.
133 213 storres
    intvl               = "" # Taylor interval
134 213 storres
    terr                = 0  # Taylor error.
135 213 storres
    iterCount = 0
136 213 storres
    htrnSet = set()
137 213 storres
    ### Timers and counters.
138 213 storres
    wallTimeStart                   = 0
139 213 storres
    cpuTimeStart                    = 0
140 213 storres
    taylCondFailedCount             = 0
141 213 storres
    coppCondFailedCount             = 0
142 213 storres
    resultCondFailedCount           = 0
143 213 storres
    coppCondFailed                  = False
144 213 storres
    resultCondFailed                = False
145 213 storres
    globalResultsList               = []
146 213 storres
    basisConstructionsCount         = 0
147 213 storres
    basisConstructionsFullTime      = 0
148 213 storres
    basisConstructionTime           = 0
149 213 storres
    reductionsCount                 = 0
150 213 storres
    reductionsFullTime              = 0
151 213 storres
    reductionTime                   = 0
152 213 storres
    resultantsComputationsCount     = 0
153 213 storres
    resultantsComputationsFullTime  = 0
154 213 storres
    resultantsComputationTime       = 0
155 213 storres
    rootsComputationsCount          = 0
156 213 storres
    rootsComputationsFullTime       = 0
157 213 storres
    rootsComputationTime            = 0
158 213 storres
    print
159 213 storres
    ## Global times are started here.
160 213 storres
    wallTimeStart                   = walltime()
161 213 storres
    cpuTimeStart                    = cputime()
162 213 storres
    ## Main loop.
163 213 storres
    while True:
164 213 storres
        if lb >= sdub:
165 213 storres
            print "Lower bound reached upper bound."
166 213 storres
            break
167 213 storres
        if iterCount == maxIter:
168 213 storres
            print "Reached maxIter. Aborting"
169 213 storres
            break
170 213 storres
        iterCount += 1
171 213 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
172 213 storres
            "log2(numbers)."
173 213 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
174 213 storres
        prceSo = slz_compute_polynomial_and_interval(scaledfSo,
175 213 storres
                                                     degreeSo,
176 213 storres
                                                     lb,
177 213 storres
                                                     ub,
178 213 storres
                                                     polyApproxAccur)
179 213 storres
        ### Convert back the data into Sage space.
180 213 storres
        (floatP, floatPcv, intvl, ic, terr) = \
181 213 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
182 213 storres
                                                 prceSo[1], prceSo[2],
183 213 storres
                                                 prceSo[3]))
184 213 storres
        intvl = RRIF(intvl)
185 213 storres
        ## Clean-up Sollya stuff.
186 213 storres
        for elem in prceSo:
187 213 storres
            sollya_lib_clear_obj(elem)
188 213 storres
        #print  floatP, floatPcv, intvl, ic, terr
189 213 storres
        #print floatP
190 213 storres
        #print intvl.endpoints()[0].n(), \
191 213 storres
        #      ic.n(),
192 213 storres
        #intvl.endpoints()[1].n()
193 213 storres
        ### Check returned data.
194 213 storres
        #### Is approximation error OK?
195 213 storres
        if terr > polyApproxAccur:
196 213 storres
            exceptionErrorMess  = \
197 213 storres
                "Approximation failed - computed error:" + \
198 213 storres
                str(terr) + " - target error: "
199 213 storres
            exceptionErrorMess += \
200 213 storres
                str(polyApproxAccur) + ". Aborting!"
201 213 storres
            raise Exception(exceptionErrorMess)
202 213 storres
        #### Is lower bound OK?
203 213 storres
        if lb != intvl.endpoints()[0]:
204 213 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
205 213 storres
                               str(lb) + ". Aborting!"
206 213 storres
            raise Exception(exceptionErrorMess)
207 213 storres
        #### Set upper bound.
208 213 storres
        if ub > intvl.endpoints()[1]:
209 213 storres
            ub = intvl.endpoints()[1]
210 213 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
211 213 storres
            "log2(numbers)."
212 213 storres
            taylCondFailedCount += 1
213 213 storres
        #### Is interval not degenerate?
214 213 storres
        if lb >= ub:
215 213 storres
            exceptionErrorMess = "Degenerate interval: " + \
216 213 storres
                                "lowerBound(" + str(lb) +\
217 213 storres
                                ")>= upperBound(" + str(ub) + \
218 213 storres
                                "). Aborting!"
219 213 storres
            raise Exception(exceptionErrorMess)
220 213 storres
        #### Is interval center ok?
221 213 storres
        if ic <= lb or ic >= ub:
222 213 storres
            exceptionErrorMess =  "Invalid interval center for " + \
223 213 storres
                                str(lb) + ',' + str(ic) + ',' +  \
224 213 storres
                                str(ub) + ". Aborting!"
225 213 storres
            raise Exception(exceptionErrorMess)
226 213 storres
        ##### Current interval width and reset future interval width.
227 213 storres
        bw = ub - lb
228 213 storres
        nbw = 0
229 213 storres
        icAsInt = int(ic * toIntegerFactor)
230 213 storres
        #### The following ratio is always >= 1. In case we may want to
231 213 storres
        #    enlarge the interval
232 213 storres
        curTaylErrRat = polyApproxAccur / terr
233 213 storres
        ### Make the  integral transformations.
234 213 storres
        #### Bounds and interval center.
235 213 storres
        intIc = int(ic * toIntegerFactor)
236 213 storres
        intLb = int(lb * toIntegerFactor) - intIc
237 213 storres
        intUb = int(ub * toIntegerFactor) - intIc
238 213 storres
        #
239 213 storres
        #### Polynomials
240 213 storres
        basisConstructionTime         = cputime()
241 213 storres
        ##### To a polynomial with rational coefficients with rational arguments
242 213 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
243 213 storres
        ##### To a polynomial with rational coefficients with integer arguments
244 213 storres
        ratIntP = \
245 213 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
246 213 storres
        #####  Ultimately a multivariate polynomial with integer coefficients
247 213 storres
        #      with integer arguments.
248 213 storres
        coppersmithTuple = \
249 213 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
250 213 storres
                                                        precision,
251 213 storres
                                                        targetHardnessToRound,
252 213 storres
                                                        i, t)
253 213 storres
        #### Recover Coppersmith information.
254 213 storres
        intIntP = coppersmithTuple[0]
255 213 storres
        N = coppersmithTuple[1]
256 213 storres
        nAtAlpha = N^alpha
257 213 storres
        tBound = coppersmithTuple[2]
258 213 storres
        leastCommonMultiple = coppersmithTuple[3]
259 213 storres
        iBound = max(abs(intLb),abs(intUb))
260 213 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
261 213 storres
        basisConstructionsCount           += 1
262 213 storres
        reductionTime                     = cputime()
263 213 storres
        #### Compute the reduced polynomials.
264 213 storres
        ccReducedPolynomialsList =  \
265 213 storres
            slz_compute_coppersmith_reduced_polynomials_with_lattice_volume(intIntP,
266 213 storres
                                                        alpha,
267 213 storres
                                                        N,
268 213 storres
                                                        iBound,
269 213 storres
                                                        tBound)
270 213 storres
        if ccReducedPolynomialsList is None:
271 213 storres
            raise Exception("Reduction failed.")
272 213 storres
        reductionsFullTime    += cputime(reductionTime)
273 213 storres
        reductionsCount       += 1
274 213 storres
        if len(ccReducedPolynomialsList) < 2:
275 213 storres
            print "Nothing to form resultants with."
276 213 storres
            print
277 213 storres
            coppCondFailedCount += 1
278 213 storres
            coppCondFailed = True
279 213 storres
            ##### Apply a different shrink factor according to
280 213 storres
            #  the number of compliant polynomials.
281 213 storres
            if len(ccReducedPolynomialsList) == 0:
282 213 storres
                ub = lb + bw * noCoppersmithIntervalShrink
283 213 storres
            else: # At least one compliant polynomial.
284 213 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
285 213 storres
            if ub > sdub:
286 213 storres
                ub = sdub
287 213 storres
            if lb == ub:
288 213 storres
                raise Exception("Cant shrink interval \
289 213 storres
                anymore to get Coppersmith condition.")
290 213 storres
            nbw = 0
291 213 storres
            continue
292 213 storres
        #### We have at least two polynomials.
293 213 storres
        #    Let us try to compute resultants.
294 213 storres
        #    For each resultant computed, go for the solutions.
295 213 storres
        ##### Build the pairs list.
296 213 storres
        polyPairsList           = []
297 213 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
298 213 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
299 213 storres
                                         len(ccReducedPolynomialsList)):
300 213 storres
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
301 213 storres
                                      ccReducedPolynomialsList[polyInnerIndex]))
302 213 storres
        #### Actual root search.
303 213 storres
        rootsSet            = set()
304 213 storres
        hasNonNullResultant = False
305 213 storres
        for polyPair in polyPairsList:
306 213 storres
            if hasNonNullResultant:
307 213 storres
                break
308 213 storres
            resultantsComputationTime   = cputime()
309 213 storres
            currentResultantI = \
310 213 storres
                slz_resultant(polyPair[0],
311 213 storres
                              polyPair[1],
312 213 storres
                              t)
313 213 storres
            resultantsComputationsCount    += 1
314 213 storres
            if currentResultantI is None:
315 213 storres
                resultantsComputationsFullTime +=  \
316 213 storres
                    cputime(resultantsComputationTime)
317 213 storres
                print "Nul resultant"
318 213 storres
                continue # Next polyPair.
319 213 storres
            currentResultantT = \
320 213 storres
                slz_resultant(polyPair[0],
321 213 storres
                              polyPair[1],
322 213 storres
                              i)
323 213 storres
            resultantsComputationsFullTime += cputime(resultantsComputationTime)
324 213 storres
            resultantsComputationsCount    += 1
325 213 storres
            if currentResultantT is None:
326 213 storres
                print "Nul resultant"
327 213 storres
                continue # Next polyPair.
328 213 storres
            else:
329 213 storres
                hasNonNullResultant = True
330 213 storres
            #### We have a non null resultants pair. From now on, whatever the
331 213 storres
            #    root search yields, no extra root search is necessary.
332 213 storres
            #### A constant resultant leads to no root. Root search is done.
333 213 storres
            if currentResultantI.degree() < 1:
334 213 storres
                print "Resultant is constant:", currentResultantI
335 213 storres
                break # Next polyPair and should break.
336 213 storres
            if currentResultantT.degree() < 1:
337 213 storres
                print "Resultant is constant:", currentResultantT
338 213 storres
                break # Next polyPair and should break.
339 213 storres
            #### Actual roots computation.
340 213 storres
            rootsComputationTime       = cputime()
341 213 storres
            ##### Compute i roots
342 213 storres
            iRootsList = Zi(currentResultantI).roots()
343 213 storres
            rootsComputationsCount      +=  1
344 213 storres
            if len(iRootsList) == 0:
345 213 storres
                rootsComputationsFullTime   =   cputime(rootsComputationTime)
346 213 storres
                print "No roots in \"i\"."
347 213 storres
                break # No roots in i.
348 213 storres
            tRootsList = Zt(currentResultantT).roots()
349 213 storres
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
350 213 storres
            rootsComputationsCount      +=  1
351 213 storres
            if len(tRootsList) == 0:
352 213 storres
                print "No roots in \"t\"."
353 213 storres
                break # No roots in i.
354 213 storres
            ##### For each iRoot, get a tRoot and check against the polynomials.
355 213 storres
            for iRoot in iRootsList:
356 213 storres
                ####### Roots returned by roots() are (value, multiplicity)
357 213 storres
                #       tuples.
358 213 storres
                #print "iRoot:", iRoot
359 213 storres
                for tRoot in tRootsList:
360 213 storres
                ###### Use the tRoot against each polynomial, alternatively.
361 213 storres
                    if polyPair[0](iRoot[0],tRoot[0]) != 0:
362 213 storres
                        continue
363 213 storres
                    if polyPair[1](iRoot[0],tRoot[0]) != 0:
364 213 storres
                        continue
365 213 storres
                    rootsSet.add((iRoot[0], tRoot[0]))
366 213 storres
            # End of roots computation.
367 213 storres
        # End loop for polyPair in polyParsList.  Will break at next iteration.
368 213 storres
        # since a non null resultant was found.
369 213 storres
        #### Prepare for results for the current interval..
370 213 storres
        intervalResultsList = []
371 213 storres
        intervalResultsList.append((lb, ub))
372 213 storres
        #### Check roots.
373 213 storres
        rootsResultsList = []
374 213 storres
        for root in rootsSet:
375 213 storres
            specificRootResultsList = []
376 213 storres
            failingBounds = []
377 213 storres
            intIntPdivN = intIntP(root[0], root[1]) / N
378 213 storres
            if int(intIntPdivN) != intIntPdivN:
379 213 storres
                continue # Next root
380 213 storres
            # Root qualifies for modular equation, test it for hardness to round.
381 213 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + root[0]) / toIntegerFactor)
382 213 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
383 213 storres
            #print scalingFunction
384 213 storres
            scaledHardToRoundCaseAsFloat = \
385 213 storres
                scalingFunction(hardToRoundCaseAsFloat)
386 213 storres
            print "Candidate HTRNc at x =", \
387 213 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
388 213 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
389 213 storres
                           function,
390 213 storres
                           2^-(targetHardnessToRound),
391 213 storres
                           RRR):
392 213 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
393 213 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
394 213 storres
                    print "Found in interval."
395 213 storres
                else:
396 213 storres
                    print "Found out of interval."
397 213 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
398 213 storres
                # Check the root is in the bounds
399 213 storres
                if abs(root[0]) > iBound or abs(root[1]) > tBound:
400 213 storres
                    print "Root", root, "is out of bounds for modular equation."
401 213 storres
                    if abs(root[0]) > iBound:
402 213 storres
                        print "root[0]:", root[0]
403 213 storres
                        print "i bound:", iBound
404 213 storres
                        failingBounds.append('i')
405 213 storres
                        failingBounds.append(root[0])
406 213 storres
                        failingBounds.append(iBound)
407 213 storres
                    if abs(root[1]) > tBound:
408 213 storres
                        print "root[1]:", root[1]
409 213 storres
                        print "t bound:", tBound
410 213 storres
                        failingBounds.append('t')
411 213 storres
                        failingBounds.append(root[1])
412 213 storres
                        failingBounds.append(tBound)
413 213 storres
                if len(failingBounds) > 0:
414 213 storres
                    specificRootResultsList.append(failingBounds)
415 213 storres
            else: # From slz_is_htrn...
416 213 storres
                print "is not an HTRN case."
417 213 storres
            if len(specificRootResultsList) > 0:
418 213 storres
                rootsResultsList.append(specificRootResultsList)
419 213 storres
        if len(rootsResultsList) > 0:
420 213 storres
            intervalResultsList.append(rootsResultsList)
421 213 storres
        ### Check if a non null resultant was found. If not shrink the interval.
422 213 storres
        if not hasNonNullResultant:
423 213 storres
            print "Only null resultants for this reduction, shrinking interval."
424 213 storres
            resultCondFailed      =  True
425 213 storres
            resultCondFailedCount += 1
426 213 storres
            ### Shrink interval for next iteration.
427 213 storres
            ub = lb + bw * onlyNullResultantsShrink
428 213 storres
            if ub > sdub:
429 213 storres
                ub = sdub
430 213 storres
            nbw = 0
431 213 storres
            continue
432 213 storres
        #### An intervalResultsList has at least the bounds.
433 213 storres
        globalResultsList.append(intervalResultsList)
434 213 storres
        #### Compute an incremented width for next upper bound, only
435 213 storres
        #    if not Coppersmith condition nor resultant condition
436 213 storres
        #    failed at the previous run.
437 213 storres
        if not coppCondFailed and not resultCondFailed:
438 213 storres
            nbw = noErrorIntervalStretch * bw
439 213 storres
        else:
440 213 storres
            nbw = bw
441 213 storres
        ##### Reset the failure flags. They will be raised
442 213 storres
        #     again if needed.
443 213 storres
        coppCondFailed   = False
444 213 storres
        resultCondFailed = False
445 213 storres
        #### For next iteration (at end of loop)
446 213 storres
        #print "nbw:", nbw
447 213 storres
        lb  = ub
448 213 storres
        ub += nbw
449 213 storres
        if ub > sdub:
450 213 storres
            ub = sdub
451 213 storres
        print
452 213 storres
    # End while True
453 213 storres
    ## Main loop just ended.
454 213 storres
    globalWallTime = walltime(wallTimeStart)
455 213 storres
    globalCpuTime  = cputime(cpuTimeStart)
456 213 storres
    ## Output results
457 213 storres
    print ; print "Intervals and HTRNs" ; print
458 213 storres
    for intervalResultsList in globalResultsList:
459 213 storres
        print "[", intervalResultsList[0][0], ",",intervalResultsList[0][1], "]",
460 213 storres
        if len(intervalResultsList) > 1:
461 213 storres
            rootsResultsList = intervalResultsList[1]
462 213 storres
            for specificRootResultsList in rootsResultsList:
463 213 storres
                print "\t", specificRootResultsList[0],
464 213 storres
                if len(specificRootResultsList) > 1:
465 213 storres
                    print specificRootResultsList[1],
466 213 storres
        print ; print
467 213 storres
    #print globalResultsList
468 213 storres
    #
469 213 storres
    print "Timers and counters"
470 213 storres
    print
471 213 storres
    print "Number of iterations:", iterCount
472 213 storres
    print "Taylor condition failures:", taylCondFailedCount
473 213 storres
    print "Coppersmith condition failures:", coppCondFailedCount
474 213 storres
    print "Resultant condition failures:", resultCondFailedCount
475 213 storres
    print "Iterations count: ", iterCount
476 213 storres
    print "Number of intervals:", len(globalResultsList)
477 213 storres
    print "Number of basis constructions:", basisConstructionsCount
478 213 storres
    print "Total CPU time spent in basis constructions:", \
479 213 storres
        basisConstructionsFullTime
480 213 storres
    if basisConstructionsCount != 0:
481 213 storres
        print "Average basis construction CPU time:", \
482 213 storres
            basisConstructionsFullTime/basisConstructionsCount
483 213 storres
    print "Number of reductions:", reductionsCount
484 213 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
485 213 storres
    if reductionsCount != 0:
486 213 storres
        print "Average reduction CPU time:", \
487 213 storres
            reductionsFullTime/reductionsCount
488 213 storres
    print "Number of resultants computation rounds:", \
489 213 storres
        resultantsComputationsCount
490 213 storres
    print "Total CPU time spent in resultants computation rounds:", \
491 213 storres
        resultantsComputationsFullTime
492 213 storres
    if resultantsComputationsCount != 0:
493 213 storres
        print "Average resultants computation round CPU time:", \
494 213 storres
            resultantsComputationsFullTime/resultantsComputationsCount
495 213 storres
    print "Number of root finding rounds:", rootsComputationsCount
496 213 storres
    print "Total CPU time spent in roots finding rounds:", \
497 213 storres
        rootsComputationsFullTime
498 213 storres
    if rootsComputationsCount != 0:
499 213 storres
        print "Average roots finding round CPU time:", \
500 213 storres
            rootsComputationsFullTime/rootsComputationsCount
501 213 storres
    print "Global Wall time:", globalWallTime
502 213 storres
    print "Global CPU time:", globalCpuTime
503 213 storres
    ## Output counters
504 213 storres
# End srs_compute_lattice_volume
505 213 storres
506 213 storres
"""
507 194 storres
SLZ runtime function.
508 194 storres
"""
509 194 storres
510 194 storres
def srs_run_SLZ_v01(inputFunction,
511 194 storres
                    inputLowerBound,
512 194 storres
                    inputUpperBound,
513 194 storres
                    alpha,
514 194 storres
                    degree,
515 194 storres
                    precision,
516 194 storres
                    emin,
517 194 storres
                    emax,
518 194 storres
                    targetHardnessToRound,
519 194 storres
                    debug = False):
520 194 storres
521 194 storres
    if debug:
522 194 storres
        print "Function                :", inputFunction
523 194 storres
        print "Lower bound             :", inputLowerBound
524 194 storres
        print "Upper bounds            :", inputUpperBound
525 194 storres
        print "Alpha                   :", alpha
526 194 storres
        print "Degree                  :", degree
527 194 storres
        print "Precision               :", precision
528 194 storres
        print "Emin                    :", emin
529 194 storres
        print "Emax                    :", emax
530 194 storres
        print "Target hardness-to-round:", targetHardnessToRound
531 194 storres
        print
532 194 storres
    ## Important constants.
533 194 storres
    ### Stretch the interval if no error happens.
534 194 storres
    noErrorIntervalStretch = 1 + 2^(-5)
535 194 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
536 194 storres
    #   by the following factor.
537 194 storres
    noCoppersmithIntervalShrink = 1/2
538 194 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
539 194 storres
    #   shrink the interval by the following factor.
540 194 storres
    oneCoppersmithIntervalShrink = 3/4
541 194 storres
    #### If only null resultants are found, shrink the interval by the
542 194 storres
    #    following factor.
543 194 storres
    onlyNullResultantsShrink     = 3/4
544 194 storres
    ## Structures.
545 194 storres
    RRR         = RealField(precision)
546 194 storres
    RRIF        = RealIntervalField(precision)
547 194 storres
    ## Converting input bound into the "right" field.
548 194 storres
    lowerBound = RRR(inputLowerBound)
549 194 storres
    upperBound = RRR(inputUpperBound)
550 194 storres
    ## Before going any further, check domain and image binade conditions.
551 194 storres
    print inputFunction(1).n()
552 206 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
553 206 storres
    if output is None:
554 206 storres
        print "Invalid domain/image binades. Domain:",\
555 206 storres
        lowerBound, upperBound, "Images:", \
556 206 storres
        inputFunction(lowerBound), inputFunction(upperBound)
557 206 storres
        raise Exception("Invalid domain/image binades.")
558 206 storres
    lb = output[0] ; ub = output[1]
559 206 storres
    if lb is None or lb != lowerBound or ub != upperBound:
560 194 storres
        print "lb:", lb, " - ub:", ub
561 194 storres
        print "Invalid domain/image binades. Domain:",\
562 194 storres
        lowerBound, upperBound, "Images:", \
563 194 storres
        inputFunction(lowerBound), inputFunction(upperBound)
564 194 storres
        raise Exception("Invalid domain/image binades.")
565 194 storres
    #
566 194 storres
    ## Progam initialization
567 194 storres
    ### Approximation polynomial accuracy and hardness to round.
568 194 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
569 194 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
570 194 storres
    ### Significand to integer conversion ratio.
571 194 storres
    toIntegerFactor           = 2^(precision-1)
572 194 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
573 194 storres
    ### Variables and rings for polynomials and root searching.
574 194 storres
    i=var('i')
575 194 storres
    t=var('t')
576 194 storres
    inputFunctionVariable = inputFunction.variables()[0]
577 194 storres
    function = inputFunction.subs({inputFunctionVariable:i})
578 194 storres
    #  Polynomial Rings over the integers, for root finding.
579 194 storres
    Zi = ZZ[i]
580 194 storres
    Zt = ZZ[t]
581 194 storres
    Zit = ZZ[i,t]
582 194 storres
    ## Number of iterations limit.
583 194 storres
    maxIter = 100000
584 194 storres
    #
585 194 storres
    ## Compute the scaled function and the degree, in their Sollya version
586 194 storres
    #  once for all.
587 194 storres
    (scaledf, sdlb, sdub, silb, siub) = \
588 194 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
589 194 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
590 194 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
591 194 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
592 194 storres
    #
593 194 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
594 194 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
595 194 storres
    (unscalingFunction, scalingFunction) = \
596 194 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
597 194 storres
    #print scalingFunction, unscalingFunction
598 194 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
599 194 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
600 194 storres
    if internalSollyaPrec < 192:
601 194 storres
        internalSollyaPrec = 192
602 194 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
603 194 storres
    print "Sollya internal precision:", internalSollyaPrec
604 194 storres
    ## Some variables.
605 194 storres
    ### General variables
606 194 storres
    lb                  = sdlb
607 194 storres
    ub                  = sdub
608 194 storres
    nbw                 = 0
609 194 storres
    intervalUlp         = ub.ulp()
610 194 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
611 194 storres
    ic                  = 0
612 194 storres
    icAsInt             = 0    # Set from ic.
613 194 storres
    solutionsSet        = set()
614 194 storres
    tsErrorWidth        = []
615 194 storres
    csErrorVectors      = []
616 194 storres
    csVectorsResultants = []
617 194 storres
    floatP              = 0  # Taylor polynomial.
618 194 storres
    floatPcv            = 0  # Ditto with variable change.
619 194 storres
    intvl               = "" # Taylor interval
620 194 storres
    terr                = 0  # Taylor error.
621 194 storres
    iterCount = 0
622 194 storres
    htrnSet = set()
623 194 storres
    ### Timers and counters.
624 194 storres
    wallTimeStart                   = 0
625 194 storres
    cpuTimeStart                    = 0
626 194 storres
    taylCondFailedCount             = 0
627 194 storres
    coppCondFailedCount             = 0
628 194 storres
    resultCondFailedCount           = 0
629 194 storres
    coppCondFailed                  = False
630 194 storres
    resultCondFailed                = False
631 194 storres
    globalResultsList               = []
632 194 storres
    basisConstructionsCount         = 0
633 194 storres
    basisConstructionsFullTime      = 0
634 194 storres
    basisConstructionTime           = 0
635 194 storres
    reductionsCount                 = 0
636 194 storres
    reductionsFullTime              = 0
637 194 storres
    reductionTime                   = 0
638 194 storres
    resultantsComputationsCount     = 0
639 194 storres
    resultantsComputationsFullTime  = 0
640 194 storres
    resultantsComputationTime       = 0
641 194 storres
    rootsComputationsCount          = 0
642 194 storres
    rootsComputationsFullTime       = 0
643 194 storres
    rootsComputationTime            = 0
644 194 storres
    print
645 194 storres
    ## Global times are started here.
646 194 storres
    wallTimeStart                   = walltime()
647 194 storres
    cpuTimeStart                    = cputime()
648 194 storres
    ## Main loop.
649 194 storres
    while True:
650 194 storres
        if lb >= sdub:
651 194 storres
            print "Lower bound reached upper bound."
652 194 storres
            break
653 194 storres
        if iterCount == maxIter:
654 194 storres
            print "Reached maxIter. Aborting"
655 194 storres
            break
656 194 storres
        iterCount += 1
657 194 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
658 194 storres
            "log2(numbers)."
659 194 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
660 194 storres
        prceSo = slz_compute_polynomial_and_interval(scaledfSo,
661 194 storres
                                                     degreeSo,
662 194 storres
                                                     lb,
663 194 storres
                                                     ub,
664 194 storres
                                                     polyApproxAccur)
665 194 storres
        ### Convert back the data into Sage space.
666 194 storres
        (floatP, floatPcv, intvl, ic, terr) = \
667 194 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
668 194 storres
                                                 prceSo[1], prceSo[2],
669 194 storres
                                                 prceSo[3]))
670 194 storres
        intvl = RRIF(intvl)
671 194 storres
        ## Clean-up Sollya stuff.
672 194 storres
        for elem in prceSo:
673 194 storres
            sollya_lib_clear_obj(elem)
674 194 storres
        #print  floatP, floatPcv, intvl, ic, terr
675 194 storres
        #print floatP
676 194 storres
        #print intvl.endpoints()[0].n(), \
677 194 storres
        #      ic.n(),
678 194 storres
        #intvl.endpoints()[1].n()
679 194 storres
        ### Check returned data.
680 194 storres
        #### Is approximation error OK?
681 194 storres
        if terr > polyApproxAccur:
682 194 storres
            exceptionErrorMess  = \
683 194 storres
                "Approximation failed - computed error:" + \
684 194 storres
                str(terr) + " - target error: "
685 194 storres
            exceptionErrorMess += \
686 194 storres
                str(polyApproxAccur) + ". Aborting!"
687 194 storres
            raise Exception(exceptionErrorMess)
688 194 storres
        #### Is lower bound OK?
689 194 storres
        if lb != intvl.endpoints()[0]:
690 194 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
691 194 storres
                               str(lb) + ". Aborting!"
692 194 storres
            raise Exception(exceptionErrorMess)
693 194 storres
        #### Set upper bound.
694 194 storres
        if ub > intvl.endpoints()[1]:
695 194 storres
            ub = intvl.endpoints()[1]
696 194 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
697 194 storres
            "log2(numbers)."
698 194 storres
            taylCondFailedCount += 1
699 194 storres
        #### Is interval not degenerate?
700 194 storres
        if lb >= ub:
701 194 storres
            exceptionErrorMess = "Degenerate interval: " + \
702 194 storres
                                "lowerBound(" + str(lb) +\
703 194 storres
                                ")>= upperBound(" + str(ub) + \
704 194 storres
                                "). Aborting!"
705 194 storres
            raise Exception(exceptionErrorMess)
706 194 storres
        #### Is interval center ok?
707 194 storres
        if ic <= lb or ic >= ub:
708 194 storres
            exceptionErrorMess =  "Invalid interval center for " + \
709 194 storres
                                str(lb) + ',' + str(ic) + ',' +  \
710 194 storres
                                str(ub) + ". Aborting!"
711 194 storres
            raise Exception(exceptionErrorMess)
712 194 storres
        ##### Current interval width and reset future interval width.
713 194 storres
        bw = ub - lb
714 194 storres
        nbw = 0
715 194 storres
        icAsInt = int(ic * toIntegerFactor)
716 194 storres
        #### The following ratio is always >= 1. In case we may want to
717 194 storres
        #  enlarge the interval
718 194 storres
        curTaylErrRat = polyApproxAccur / terr
719 194 storres
        ## Make the  integral transformations.
720 194 storres
        ### First for interval center and bounds.
721 194 storres
        intIc = int(ic * toIntegerFactor)
722 194 storres
        intLb = int(lb * toIntegerFactor) - intIc
723 194 storres
        intUb = int(ub * toIntegerFactor) - intIc
724 194 storres
        #
725 194 storres
        #### For polynomials
726 194 storres
        basisConstructionTime         = cputime()
727 194 storres
        ##### To a polynomial with rational coefficients with rational arguments
728 194 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
729 194 storres
        ##### To a polynomial with rational coefficients with integer arguments
730 194 storres
        ratIntP = \
731 194 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
732 194 storres
        #####  Ultimately a polynomial with integer coefficients with integer
733 194 storres
        #      arguments.
734 194 storres
        coppersmithTuple = \
735 194 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
736 194 storres
                                                        precision,
737 194 storres
                                                        targetHardnessToRound,
738 194 storres
                                                        i, t)
739 194 storres
        #### Recover Coppersmith information.
740 194 storres
        intIntP = coppersmithTuple[0]
741 194 storres
        N = coppersmithTuple[1]
742 194 storres
        nAtAlpha = N^alpha
743 194 storres
        tBound = coppersmithTuple[2]
744 194 storres
        leastCommonMultiple = coppersmithTuple[3]
745 194 storres
        iBound = max(abs(intLb),abs(intUb))
746 194 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
747 194 storres
        basisConstructionsCount           += 1
748 194 storres
        reductionTime                     = cputime()
749 194 storres
        # Compute the reduced polynomials.
750 194 storres
        ccReducedPolynomialsList =  \
751 212 storres
                slz_compute_coppersmith_reduced_polynomials(intIntP,
752 212 storres
                                                            alpha,
753 212 storres
                                                            N,
754 212 storres
                                                            iBound,
755 212 storres
                                                            tBound)
756 194 storres
        if ccReducedPolynomialsList is None:
757 194 storres
            raise Exception("Reduction failed.")
758 194 storres
        reductionsFullTime    += cputime(reductionTime)
759 194 storres
        reductionsCount       += 1
760 194 storres
        if len(ccReducedPolynomialsList) < 2:
761 194 storres
            print "Nothing to form resultants with."
762 194 storres
            print
763 194 storres
            coppCondFailedCount += 1
764 194 storres
            coppCondFailed = True
765 194 storres
            ##### Apply a different shrink factor according to
766 194 storres
            #  the number of compliant polynomials.
767 194 storres
            if len(ccReducedPolynomialsList) == 0:
768 194 storres
                ub = lb + bw * noCoppersmithIntervalShrink
769 194 storres
            else: # At least one compliant polynomial.
770 194 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
771 194 storres
            if ub > sdub:
772 194 storres
                ub = sdub
773 194 storres
            if lb == ub:
774 194 storres
                raise Exception("Cant shrink interval \
775 194 storres
                anymore to get Coppersmith condition.")
776 194 storres
            nbw = 0
777 194 storres
            continue
778 194 storres
        #### We have at least two polynomials.
779 194 storres
        #    Let us try to compute resultants.
780 194 storres
        resultantsComputationTime      = cputime()
781 194 storres
        resultantsInTTuplesList = []
782 194 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
783 194 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
784 194 storres
                                         len(ccReducedPolynomialsList)):
785 194 storres
                resultantTuple = \
786 194 storres
                slz_resultant_tuple(ccReducedPolynomialsList[polyOuterIndex],
787 194 storres
                                ccReducedPolynomialsList[polyInnerIndex],
788 194 storres
                                t)
789 194 storres
                if len(resultantTuple) > 2:
790 194 storres
                    #print resultantTuple[2]
791 194 storres
                    resultantsInTTuplesList.append(resultantTuple)
792 194 storres
                else:
793 194 storres
                    print "No non nul resultant"
794 194 storres
        print len(resultantsInTTuplesList), "resultant(s) in t tuple(s) created."
795 194 storres
        resultantsComputationsFullTime += cputime(resultantsComputationTime)
796 194 storres
        resultantsComputationsCount    += 1
797 194 storres
        if len(resultantsInTTuplesList) == 0:
798 194 storres
            print "Only null resultants, shrinking interval."
799 194 storres
            resultCondFailed      =  True
800 194 storres
            resultCondFailedCount += 1
801 194 storres
            ### Shrink interval for next iteration.
802 194 storres
            ub = lb + bw * onlyNullResultantsShrink
803 194 storres
            if ub > sdub:
804 194 storres
                ub = sdub
805 194 storres
            nbw = 0
806 194 storres
            continue
807 194 storres
        #### Compute roots.
808 194 storres
        rootsComputationTime       = cputime()
809 194 storres
        reducedPolynomialsRootsSet = set()
810 194 storres
        ##### Solve in the second variable since resultants are in the first
811 194 storres
        #     variable.
812 194 storres
        for resultantInTTuple in resultantsInTTuplesList:
813 194 storres
            currentResultant = resultantInTTuple[2]
814 194 storres
            ##### If the resultant degree is not at least 1, there are no roots.
815 194 storres
            if currentResultant.degree() < 1:
816 194 storres
                print "Resultant is constant:", currentResultant
817 194 storres
                continue # Next resultantInTTuple
818 194 storres
            ##### Compute i roots
819 194 storres
            iRootsList = Zi(currentResultant).roots()
820 194 storres
            ##### For each iRoot, compute the corresponding tRoots and check
821 194 storres
            #     them in the input polynomial.
822 194 storres
            for iRoot in iRootsList:
823 194 storres
                ####### Roots returned by roots() are (value, multiplicity)
824 194 storres
                #       tuples.
825 194 storres
                #print "iRoot:", iRoot
826 194 storres
                ###### Use the tRoot against each polynomial, alternatively.
827 194 storres
                for indexInTuple in range(0,2):
828 194 storres
                    currentPolynomial = resultantInTTuple[indexInTuple]
829 194 storres
                    ####### If the polynomial is univariate, just drop it.
830 194 storres
                    if len(currentPolynomial.variables()) < 2:
831 194 storres
                        print "    Current polynomial is not in two variables."
832 194 storres
                        continue # Next indexInTuple
833 194 storres
                    tRootsList = \
834 194 storres
                        Zt(currentPolynomial.subs({currentPolynomial.variables()[0]:iRoot[0]})).roots()
835 194 storres
                    ####### The tRootsList can be empty, hence the test.
836 194 storres
                    if len(tRootsList) == 0:
837 194 storres
                        print "    No t root."
838 194 storres
                        continue # Next indexInTuple
839 194 storres
                    for tRoot in tRootsList:
840 194 storres
                        reducedPolynomialsRootsSet.add((iRoot[0], tRoot[0]))
841 194 storres
        # End of roots computation
842 194 storres
        rootsComputationsFullTime   =   cputime(rootsComputationTime)
843 194 storres
        rootsComputationsCount      +=  1
844 194 storres
        ##### Prepare for results.
845 194 storres
        intervalResultsList = []
846 194 storres
        intervalResultsList.append((lb, ub))
847 194 storres
        #### Check roots.
848 194 storres
        rootsResultsList = []
849 194 storres
        for root in reducedPolynomialsRootsSet:
850 194 storres
            specificRootResultsList = []
851 194 storres
            failingBounds = []
852 194 storres
            intIntPdivN = intIntP(root[0], root[1]) / N
853 194 storres
            if int(intIntPdivN) != intIntPdivN:
854 194 storres
                continue # Next root
855 194 storres
            # Root qualifies for modular equation, test it for hardness to round.
856 194 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + root[0]) / toIntegerFactor)
857 194 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
858 194 storres
            #print scalingFunction
859 194 storres
            scaledHardToRoundCaseAsFloat = \
860 194 storres
                scalingFunction(hardToRoundCaseAsFloat)
861 194 storres
            print "Candidate HTRNc at x =", \
862 194 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
863 194 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
864 194 storres
                           function,
865 194 storres
                           2^-(targetHardnessToRound),
866 194 storres
                           RRR):
867 194 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
868 194 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
869 194 storres
                    print "Found in interval."
870 194 storres
                else:
871 194 storres
                    print "Found out of interval."
872 194 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
873 194 storres
                # Check the root is in the bounds
874 194 storres
                if abs(root[0]) > iBound or abs(root[1]) > tBound:
875 194 storres
                    print "Root", root, "is out of bounds."
876 194 storres
                    if abs(root[0]) > iBound:
877 194 storres
                        print "root[0]:", root[0]
878 194 storres
                        print "i bound:", iBound
879 194 storres
                        failingBounds.append('i')
880 194 storres
                        failingBounds.append(root[0])
881 194 storres
                        failingBounds.append(iBound)
882 194 storres
                    if abs(root[1]) > tBound:
883 194 storres
                        print "root[1]:", root[1]
884 194 storres
                        print "t bound:", tBound
885 194 storres
                        failingBounds.append('t')
886 194 storres
                        failingBounds.append(root[1])
887 194 storres
                        failingBounds.append(tBound)
888 194 storres
                if len(failingBounds) > 0:
889 194 storres
                    specificRootResultsList.append(failingBounds)
890 194 storres
            else: # From slz_is_htrn...
891 194 storres
                print "is not an HTRN case."
892 194 storres
            if len(specificRootResultsList) > 0:
893 194 storres
                rootsResultsList.append(specificRootResultsList)
894 194 storres
        if len(rootsResultsList) > 0:
895 194 storres
            intervalResultsList.append(rootsResultsList)
896 194 storres
        #### An intervalResultsList has at least the bounds.
897 194 storres
        globalResultsList.append(intervalResultsList)
898 194 storres
        #### Compute an incremented width for next upper bound, only
899 194 storres
        #    if not Coppersmith condition nor resultant condition
900 194 storres
        #    failed at the previous run.
901 194 storres
        if not coppCondFailed and not resultCondFailed:
902 194 storres
            nbw = noErrorIntervalStretch * bw
903 194 storres
        else:
904 194 storres
            nbw = bw
905 194 storres
        ##### Reset the failure flags. They will be raised
906 194 storres
        #     again if needed.
907 194 storres
        coppCondFailed   = False
908 194 storres
        resultCondFailed = False
909 194 storres
        #### For next iteration (at end of loop)
910 194 storres
        #print "nbw:", nbw
911 194 storres
        lb  = ub
912 194 storres
        ub += nbw
913 194 storres
        if ub > sdub:
914 194 storres
            ub = sdub
915 194 storres
        print
916 194 storres
    # End while True
917 194 storres
    ## Main loop just ended.
918 194 storres
    globalWallTime = walltime(wallTimeStart)
919 194 storres
    globalCpuTime  = cputime(cpuTimeStart)
920 194 storres
    ## Output results
921 194 storres
    print ; print "Intervals and HTRNs" ; print
922 194 storres
    for intervalResultsList in globalResultsList:
923 194 storres
        print "[", intervalResultsList[0][0], ",",intervalResultsList[0][1], "]",
924 194 storres
        if len(intervalResultsList) > 1:
925 194 storres
            rootsResultsList = intervalResultsList[1]
926 194 storres
            for specificRootResultsList in rootsResultsList:
927 194 storres
                print "\t", specificRootResultsList[0],
928 194 storres
                if len(specificRootResultsList) > 1:
929 194 storres
                    print specificRootResultsList[1],
930 194 storres
        print ; print
931 194 storres
    #print globalResultsList
932 194 storres
    #
933 194 storres
    print "Timers and counters"
934 194 storres
    print
935 194 storres
    print "Number of iterations:", iterCount
936 194 storres
    print "Taylor condition failures:", taylCondFailedCount
937 194 storres
    print "Coppersmith condition failures:", coppCondFailedCount
938 194 storres
    print "Resultant condition failures:", resultCondFailedCount
939 194 storres
    print "Iterations count: ", iterCount
940 194 storres
    print "Number of intervals:", len(globalResultsList)
941 194 storres
    print "Number of basis constructions:", basisConstructionsCount
942 194 storres
    print "Total CPU time spent in basis constructions:", \
943 194 storres
        basisConstructionsFullTime
944 194 storres
    if basisConstructionsCount != 0:
945 194 storres
        print "Average basis construction CPU time:", \
946 194 storres
            basisConstructionsFullTime/basisConstructionsCount
947 194 storres
    print "Number of reductions:", reductionsCount
948 194 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
949 194 storres
    if reductionsCount != 0:
950 194 storres
        print "Average reduction CPU time:", \
951 194 storres
            reductionsFullTime/reductionsCount
952 194 storres
    print "Number of resultants computation rounds:", \
953 194 storres
        resultantsComputationsCount
954 194 storres
    print "Total CPU time spent in resultants computation rounds:", \
955 194 storres
        resultantsComputationsFullTime
956 194 storres
    if resultantsComputationsCount != 0:
957 194 storres
        print "Average resultants computation round CPU time:", \
958 194 storres
            resultantsComputationsFullTime/resultantsComputationsCount
959 194 storres
    print "Number of root finding rounds:", rootsComputationsCount
960 194 storres
    print "Total CPU time spent in roots finding rounds:", \
961 194 storres
        rootsComputationsFullTime
962 194 storres
    if rootsComputationsCount != 0:
963 194 storres
        print "Average roots finding round CPU time:", \
964 194 storres
            rootsComputationsFullTime/rootsComputationsCount
965 194 storres
    print "Global Wall time:", globalWallTime
966 194 storres
    print "Global CPU time:", globalCpuTime
967 194 storres
    ## Output counters
968 194 storres
# End srs_runSLZ-v01
969 194 storres
970 194 storres
def srs_run_SLZ_v02(inputFunction,
971 194 storres
                    inputLowerBound,
972 194 storres
                    inputUpperBound,
973 194 storres
                    alpha,
974 194 storres
                    degree,
975 194 storres
                    precision,
976 194 storres
                    emin,
977 194 storres
                    emax,
978 194 storres
                    targetHardnessToRound,
979 194 storres
                    debug = False):
980 194 storres
    """
981 194 storres
    Changes from V1:
982 194 storres
        1- check for roots as soon as a resultant is computed;
983 194 storres
        2- once a non null resultant is found, check for roots;
984 194 storres
        3- constant resultant == no root.
985 194 storres
    """
986 194 storres
987 194 storres
    if debug:
988 194 storres
        print "Function                :", inputFunction
989 194 storres
        print "Lower bound             :", inputLowerBound
990 194 storres
        print "Upper bounds            :", inputUpperBound
991 194 storres
        print "Alpha                   :", alpha
992 194 storres
        print "Degree                  :", degree
993 194 storres
        print "Precision               :", precision
994 194 storres
        print "Emin                    :", emin
995 194 storres
        print "Emax                    :", emax
996 194 storres
        print "Target hardness-to-round:", targetHardnessToRound
997 194 storres
        print
998 194 storres
    ## Important constants.
999 194 storres
    ### Stretch the interval if no error happens.
1000 194 storres
    noErrorIntervalStretch = 1 + 2^(-5)
1001 194 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
1002 194 storres
    #   by the following factor.
1003 194 storres
    noCoppersmithIntervalShrink = 1/2
1004 194 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
1005 194 storres
    #   shrink the interval by the following factor.
1006 194 storres
    oneCoppersmithIntervalShrink = 3/4
1007 194 storres
    #### If only null resultants are found, shrink the interval by the
1008 194 storres
    #    following factor.
1009 194 storres
    onlyNullResultantsShrink     = 3/4
1010 194 storres
    ## Structures.
1011 194 storres
    RRR         = RealField(precision)
1012 194 storres
    RRIF        = RealIntervalField(precision)
1013 194 storres
    ## Converting input bound into the "right" field.
1014 194 storres
    lowerBound = RRR(inputLowerBound)
1015 194 storres
    upperBound = RRR(inputUpperBound)
1016 194 storres
    ## Before going any further, check domain and image binade conditions.
1017 194 storres
    print inputFunction(1).n()
1018 206 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
1019 206 storres
    if output is None:
1020 206 storres
        print "Invalid domain/image binades. Domain:",\
1021 206 storres
        lowerBound, upperBound, "Images:", \
1022 206 storres
        inputFunction(lowerBound), inputFunction(upperBound)
1023 206 storres
        raise Exception("Invalid domain/image binades.")
1024 206 storres
    lb = output[0] ; ub = output[1]
1025 194 storres
    if lb != lowerBound or ub != upperBound:
1026 194 storres
        print "lb:", lb, " - ub:", ub
1027 194 storres
        print "Invalid domain/image binades. Domain:",\
1028 194 storres
        lowerBound, upperBound, "Images:", \
1029 194 storres
        inputFunction(lowerBound), inputFunction(upperBound)
1030 194 storres
        raise Exception("Invalid domain/image binades.")
1031 194 storres
    #
1032 194 storres
    ## Progam initialization
1033 194 storres
    ### Approximation polynomial accuracy and hardness to round.
1034 194 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
1035 194 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
1036 194 storres
    ### Significand to integer conversion ratio.
1037 194 storres
    toIntegerFactor           = 2^(precision-1)
1038 194 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
1039 194 storres
    ### Variables and rings for polynomials and root searching.
1040 194 storres
    i=var('i')
1041 194 storres
    t=var('t')
1042 194 storres
    inputFunctionVariable = inputFunction.variables()[0]
1043 194 storres
    function = inputFunction.subs({inputFunctionVariable:i})
1044 194 storres
    #  Polynomial Rings over the integers, for root finding.
1045 194 storres
    Zi = ZZ[i]
1046 194 storres
    Zt = ZZ[t]
1047 194 storres
    Zit = ZZ[i,t]
1048 194 storres
    ## Number of iterations limit.
1049 194 storres
    maxIter = 100000
1050 194 storres
    #
1051 194 storres
    ## Compute the scaled function and the degree, in their Sollya version
1052 194 storres
    #  once for all.
1053 194 storres
    (scaledf, sdlb, sdub, silb, siub) = \
1054 194 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
1055 194 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
1056 194 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
1057 194 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
1058 194 storres
    #
1059 194 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
1060 194 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
1061 194 storres
    (unscalingFunction, scalingFunction) = \
1062 194 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
1063 194 storres
    #print scalingFunction, unscalingFunction
1064 194 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
1065 194 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
1066 194 storres
    if internalSollyaPrec < 192:
1067 194 storres
        internalSollyaPrec = 192
1068 194 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
1069 194 storres
    print "Sollya internal precision:", internalSollyaPrec
1070 194 storres
    ## Some variables.
1071 194 storres
    ### General variables
1072 194 storres
    lb                  = sdlb
1073 194 storres
    ub                  = sdub
1074 194 storres
    nbw                 = 0
1075 194 storres
    intervalUlp         = ub.ulp()
1076 194 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
1077 194 storres
    ic                  = 0
1078 194 storres
    icAsInt             = 0    # Set from ic.
1079 194 storres
    solutionsSet        = set()
1080 194 storres
    tsErrorWidth        = []
1081 194 storres
    csErrorVectors      = []
1082 194 storres
    csVectorsResultants = []
1083 194 storres
    floatP              = 0  # Taylor polynomial.
1084 194 storres
    floatPcv            = 0  # Ditto with variable change.
1085 194 storres
    intvl               = "" # Taylor interval
1086 194 storres
    terr                = 0  # Taylor error.
1087 194 storres
    iterCount = 0
1088 194 storres
    htrnSet = set()
1089 194 storres
    ### Timers and counters.
1090 194 storres
    wallTimeStart                   = 0
1091 194 storres
    cpuTimeStart                    = 0
1092 194 storres
    taylCondFailedCount             = 0
1093 194 storres
    coppCondFailedCount             = 0
1094 194 storres
    resultCondFailedCount           = 0
1095 194 storres
    coppCondFailed                  = False
1096 194 storres
    resultCondFailed                = False
1097 194 storres
    globalResultsList               = []
1098 194 storres
    basisConstructionsCount         = 0
1099 194 storres
    basisConstructionsFullTime      = 0
1100 194 storres
    basisConstructionTime           = 0
1101 194 storres
    reductionsCount                 = 0
1102 194 storres
    reductionsFullTime              = 0
1103 194 storres
    reductionTime                   = 0
1104 194 storres
    resultantsComputationsCount     = 0
1105 194 storres
    resultantsComputationsFullTime  = 0
1106 194 storres
    resultantsComputationTime       = 0
1107 194 storres
    rootsComputationsCount          = 0
1108 194 storres
    rootsComputationsFullTime       = 0
1109 194 storres
    rootsComputationTime            = 0
1110 194 storres
    print
1111 194 storres
    ## Global times are started here.
1112 194 storres
    wallTimeStart                   = walltime()
1113 194 storres
    cpuTimeStart                    = cputime()
1114 194 storres
    ## Main loop.
1115 194 storres
    while True:
1116 194 storres
        if lb >= sdub:
1117 194 storres
            print "Lower bound reached upper bound."
1118 194 storres
            break
1119 194 storres
        if iterCount == maxIter:
1120 194 storres
            print "Reached maxIter. Aborting"
1121 194 storres
            break
1122 194 storres
        iterCount += 1
1123 194 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
1124 194 storres
            "log2(numbers)."
1125 194 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
1126 194 storres
        prceSo = slz_compute_polynomial_and_interval(scaledfSo,
1127 194 storres
                                                     degreeSo,
1128 194 storres
                                                     lb,
1129 194 storres
                                                     ub,
1130 194 storres
                                                     polyApproxAccur)
1131 194 storres
        ### Convert back the data into Sage space.
1132 194 storres
        (floatP, floatPcv, intvl, ic, terr) = \
1133 194 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
1134 194 storres
                                                 prceSo[1], prceSo[2],
1135 194 storres
                                                 prceSo[3]))
1136 194 storres
        intvl = RRIF(intvl)
1137 194 storres
        ## Clean-up Sollya stuff.
1138 194 storres
        for elem in prceSo:
1139 194 storres
            sollya_lib_clear_obj(elem)
1140 194 storres
        #print  floatP, floatPcv, intvl, ic, terr
1141 194 storres
        #print floatP
1142 194 storres
        #print intvl.endpoints()[0].n(), \
1143 194 storres
        #      ic.n(),
1144 194 storres
        #intvl.endpoints()[1].n()
1145 194 storres
        ### Check returned data.
1146 194 storres
        #### Is approximation error OK?
1147 194 storres
        if terr > polyApproxAccur:
1148 194 storres
            exceptionErrorMess  = \
1149 194 storres
                "Approximation failed - computed error:" + \
1150 194 storres
                str(terr) + " - target error: "
1151 194 storres
            exceptionErrorMess += \
1152 194 storres
                str(polyApproxAccur) + ". Aborting!"
1153 194 storres
            raise Exception(exceptionErrorMess)
1154 194 storres
        #### Is lower bound OK?
1155 194 storres
        if lb != intvl.endpoints()[0]:
1156 194 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
1157 194 storres
                               str(lb) + ". Aborting!"
1158 194 storres
            raise Exception(exceptionErrorMess)
1159 194 storres
        #### Set upper bound.
1160 194 storres
        if ub > intvl.endpoints()[1]:
1161 194 storres
            ub = intvl.endpoints()[1]
1162 194 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
1163 194 storres
            "log2(numbers)."
1164 194 storres
            taylCondFailedCount += 1
1165 194 storres
        #### Is interval not degenerate?
1166 194 storres
        if lb >= ub:
1167 194 storres
            exceptionErrorMess = "Degenerate interval: " + \
1168 194 storres
                                "lowerBound(" + str(lb) +\
1169 194 storres
                                ")>= upperBound(" + str(ub) + \
1170 194 storres
                                "). Aborting!"
1171 194 storres
            raise Exception(exceptionErrorMess)
1172 194 storres
        #### Is interval center ok?
1173 194 storres
        if ic <= lb or ic >= ub:
1174 194 storres
            exceptionErrorMess =  "Invalid interval center for " + \
1175 194 storres
                                str(lb) + ',' + str(ic) + ',' +  \
1176 194 storres
                                str(ub) + ". Aborting!"
1177 194 storres
            raise Exception(exceptionErrorMess)
1178 194 storres
        ##### Current interval width and reset future interval width.
1179 194 storres
        bw = ub - lb
1180 194 storres
        nbw = 0
1181 194 storres
        icAsInt = int(ic * toIntegerFactor)
1182 194 storres
        #### The following ratio is always >= 1. In case we may want to
1183 197 storres
        #    enlarge the interval
1184 194 storres
        curTaylErrRat = polyApproxAccur / terr
1185 197 storres
        ### Make the  integral transformations.
1186 197 storres
        #### Bounds and interval center.
1187 194 storres
        intIc = int(ic * toIntegerFactor)
1188 194 storres
        intLb = int(lb * toIntegerFactor) - intIc
1189 194 storres
        intUb = int(ub * toIntegerFactor) - intIc
1190 194 storres
        #
1191 197 storres
        #### Polynomials
1192 194 storres
        basisConstructionTime         = cputime()
1193 194 storres
        ##### To a polynomial with rational coefficients with rational arguments
1194 194 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
1195 194 storres
        ##### To a polynomial with rational coefficients with integer arguments
1196 194 storres
        ratIntP = \
1197 194 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
1198 197 storres
        #####  Ultimately a multivariate polynomial with integer coefficients
1199 197 storres
        #      with integer arguments.
1200 194 storres
        coppersmithTuple = \
1201 194 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
1202 194 storres
                                                        precision,
1203 194 storres
                                                        targetHardnessToRound,
1204 194 storres
                                                        i, t)
1205 194 storres
        #### Recover Coppersmith information.
1206 194 storres
        intIntP = coppersmithTuple[0]
1207 194 storres
        N = coppersmithTuple[1]
1208 194 storres
        nAtAlpha = N^alpha
1209 194 storres
        tBound = coppersmithTuple[2]
1210 194 storres
        leastCommonMultiple = coppersmithTuple[3]
1211 194 storres
        iBound = max(abs(intLb),abs(intUb))
1212 194 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
1213 194 storres
        basisConstructionsCount           += 1
1214 194 storres
        reductionTime                     = cputime()
1215 197 storres
        #### Compute the reduced polynomials.
1216 194 storres
        ccReducedPolynomialsList =  \
1217 212 storres
                slz_compute_coppersmith_reduced_polynomials(intIntP,
1218 212 storres
                                                            alpha,
1219 212 storres
                                                            N,
1220 212 storres
                                                            iBound,
1221 212 storres
                                                            tBound)
1222 194 storres
        if ccReducedPolynomialsList is None:
1223 194 storres
            raise Exception("Reduction failed.")
1224 194 storres
        reductionsFullTime    += cputime(reductionTime)
1225 194 storres
        reductionsCount       += 1
1226 194 storres
        if len(ccReducedPolynomialsList) < 2:
1227 194 storres
            print "Nothing to form resultants with."
1228 194 storres
            print
1229 194 storres
            coppCondFailedCount += 1
1230 194 storres
            coppCondFailed = True
1231 194 storres
            ##### Apply a different shrink factor according to
1232 194 storres
            #  the number of compliant polynomials.
1233 194 storres
            if len(ccReducedPolynomialsList) == 0:
1234 194 storres
                ub = lb + bw * noCoppersmithIntervalShrink
1235 194 storres
            else: # At least one compliant polynomial.
1236 194 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
1237 194 storres
            if ub > sdub:
1238 194 storres
                ub = sdub
1239 194 storres
            if lb == ub:
1240 194 storres
                raise Exception("Cant shrink interval \
1241 194 storres
                anymore to get Coppersmith condition.")
1242 194 storres
            nbw = 0
1243 194 storres
            continue
1244 194 storres
        #### We have at least two polynomials.
1245 194 storres
        #    Let us try to compute resultants.
1246 194 storres
        #    For each resultant computed, go for the solutions.
1247 194 storres
        ##### Build the pairs list.
1248 194 storres
        polyPairsList           = []
1249 194 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
1250 194 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
1251 194 storres
                                         len(ccReducedPolynomialsList)):
1252 194 storres
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
1253 194 storres
                                      ccReducedPolynomialsList[polyInnerIndex]))
1254 197 storres
        #### Actual root search.
1255 197 storres
        rootsSet            = set()
1256 197 storres
        hasNonNullResultant = False
1257 194 storres
        for polyPair in polyPairsList:
1258 197 storres
            if hasNonNullResultant:
1259 197 storres
                break
1260 197 storres
            resultantsComputationTime   = cputime()
1261 197 storres
            currentResultant = \
1262 197 storres
                slz_resultant(polyPair[0],
1263 197 storres
                              polyPair[1],
1264 197 storres
                              t)
1265 194 storres
            resultantsComputationsFullTime += cputime(resultantsComputationTime)
1266 194 storres
            resultantsComputationsCount    += 1
1267 197 storres
            if currentResultant is None:
1268 197 storres
                print "Nul resultant"
1269 197 storres
                continue # Next polyPair.
1270 197 storres
            else:
1271 194 storres
                hasNonNullResultant = True
1272 197 storres
            #### We have a non null resultant. From now on, whatever the
1273 197 storres
            #    root search yields, no extra root search is necessary.
1274 197 storres
            #### A constant resultant leads to no root. Root search is done.
1275 194 storres
            if currentResultant.degree() < 1:
1276 194 storres
                print "Resultant is constant:", currentResultant
1277 197 storres
                continue # Next polyPair and should break.
1278 197 storres
            #### Actual roots computation.
1279 197 storres
            rootsComputationTime       = cputime()
1280 194 storres
            ##### Compute i roots
1281 194 storres
            iRootsList = Zi(currentResultant).roots()
1282 197 storres
            ##### For each iRoot, compute the corresponding tRoots and
1283 197 storres
            #     and build populate the .rootsSet.
1284 194 storres
            for iRoot in iRootsList:
1285 194 storres
                ####### Roots returned by roots() are (value, multiplicity)
1286 194 storres
                #       tuples.
1287 194 storres
                #print "iRoot:", iRoot
1288 194 storres
                ###### Use the tRoot against each polynomial, alternatively.
1289 197 storres
                for indexInPair in range(0,2):
1290 197 storres
                    currentPolynomial = polyPair[indexInPair]
1291 194 storres
                    ####### If the polynomial is univariate, just drop it.
1292 194 storres
                    if len(currentPolynomial.variables()) < 2:
1293 194 storres
                        print "    Current polynomial is not in two variables."
1294 197 storres
                        continue # Next indexInPair
1295 194 storres
                    tRootsList = \
1296 194 storres
                        Zt(currentPolynomial.subs({currentPolynomial.variables()[0]:iRoot[0]})).roots()
1297 194 storres
                    ####### The tRootsList can be empty, hence the test.
1298 194 storres
                    if len(tRootsList) == 0:
1299 194 storres
                        print "    No t root."
1300 197 storres
                        continue # Next indexInPair
1301 194 storres
                    for tRoot in tRootsList:
1302 197 storres
                        rootsSet.add((iRoot[0], tRoot[0]))
1303 197 storres
            # End of roots computation.
1304 197 storres
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
1305 197 storres
            rootsComputationsCount      +=  1
1306 197 storres
        # End loop for polyPair in polyParsList.  Will break at next iteration.
1307 197 storres
        # since a non null resultant was found.
1308 197 storres
        #### Prepare for results for the current interval..
1309 194 storres
        intervalResultsList = []
1310 194 storres
        intervalResultsList.append((lb, ub))
1311 194 storres
        #### Check roots.
1312 194 storres
        rootsResultsList = []
1313 197 storres
        for root in rootsSet:
1314 194 storres
            specificRootResultsList = []
1315 194 storres
            failingBounds = []
1316 194 storres
            intIntPdivN = intIntP(root[0], root[1]) / N
1317 194 storres
            if int(intIntPdivN) != intIntPdivN:
1318 194 storres
                continue # Next root
1319 194 storres
            # Root qualifies for modular equation, test it for hardness to round.
1320 194 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + root[0]) / toIntegerFactor)
1321 194 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
1322 194 storres
            #print scalingFunction
1323 194 storres
            scaledHardToRoundCaseAsFloat = \
1324 194 storres
                scalingFunction(hardToRoundCaseAsFloat)
1325 194 storres
            print "Candidate HTRNc at x =", \
1326 194 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
1327 194 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
1328 194 storres
                           function,
1329 194 storres
                           2^-(targetHardnessToRound),
1330 194 storres
                           RRR):
1331 194 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
1332 194 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
1333 194 storres
                    print "Found in interval."
1334 194 storres
                else:
1335 194 storres
                    print "Found out of interval."
1336 194 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
1337 194 storres
                # Check the root is in the bounds
1338 194 storres
                if abs(root[0]) > iBound or abs(root[1]) > tBound:
1339 197 storres
                    print "Root", root, "is out of bounds for modular equation."
1340 194 storres
                    if abs(root[0]) > iBound:
1341 194 storres
                        print "root[0]:", root[0]
1342 194 storres
                        print "i bound:", iBound
1343 194 storres
                        failingBounds.append('i')
1344 194 storres
                        failingBounds.append(root[0])
1345 194 storres
                        failingBounds.append(iBound)
1346 194 storres
                    if abs(root[1]) > tBound:
1347 194 storres
                        print "root[1]:", root[1]
1348 194 storres
                        print "t bound:", tBound
1349 194 storres
                        failingBounds.append('t')
1350 194 storres
                        failingBounds.append(root[1])
1351 194 storres
                        failingBounds.append(tBound)
1352 194 storres
                if len(failingBounds) > 0:
1353 194 storres
                    specificRootResultsList.append(failingBounds)
1354 194 storres
            else: # From slz_is_htrn...
1355 194 storres
                print "is not an HTRN case."
1356 194 storres
            if len(specificRootResultsList) > 0:
1357 194 storres
                rootsResultsList.append(specificRootResultsList)
1358 194 storres
        if len(rootsResultsList) > 0:
1359 194 storres
            intervalResultsList.append(rootsResultsList)
1360 197 storres
        ### Check if a non null resultant was found. If not shrink the interval.
1361 197 storres
        if not hasNonNullResultant:
1362 197 storres
            print "Only null resultants for this reduction, shrinking interval."
1363 197 storres
            resultCondFailed      =  True
1364 197 storres
            resultCondFailedCount += 1
1365 197 storres
            ### Shrink interval for next iteration.
1366 197 storres
            ub = lb + bw * onlyNullResultantsShrink
1367 197 storres
            if ub > sdub:
1368 197 storres
                ub = sdub
1369 197 storres
            nbw = 0
1370 197 storres
            continue
1371 194 storres
        #### An intervalResultsList has at least the bounds.
1372 194 storres
        globalResultsList.append(intervalResultsList)
1373 194 storres
        #### Compute an incremented width for next upper bound, only
1374 194 storres
        #    if not Coppersmith condition nor resultant condition
1375 194 storres
        #    failed at the previous run.
1376 194 storres
        if not coppCondFailed and not resultCondFailed:
1377 194 storres
            nbw = noErrorIntervalStretch * bw
1378 194 storres
        else:
1379 194 storres
            nbw = bw
1380 194 storres
        ##### Reset the failure flags. They will be raised
1381 194 storres
        #     again if needed.
1382 194 storres
        coppCondFailed   = False
1383 194 storres
        resultCondFailed = False
1384 194 storres
        #### For next iteration (at end of loop)
1385 194 storres
        #print "nbw:", nbw
1386 194 storres
        lb  = ub
1387 194 storres
        ub += nbw
1388 194 storres
        if ub > sdub:
1389 194 storres
            ub = sdub
1390 194 storres
        print
1391 194 storres
    # End while True
1392 194 storres
    ## Main loop just ended.
1393 194 storres
    globalWallTime = walltime(wallTimeStart)
1394 194 storres
    globalCpuTime  = cputime(cpuTimeStart)
1395 194 storres
    ## Output results
1396 194 storres
    print ; print "Intervals and HTRNs" ; print
1397 194 storres
    for intervalResultsList in globalResultsList:
1398 194 storres
        print "[", intervalResultsList[0][0], ",",intervalResultsList[0][1], "]",
1399 194 storres
        if len(intervalResultsList) > 1:
1400 194 storres
            rootsResultsList = intervalResultsList[1]
1401 194 storres
            for specificRootResultsList in rootsResultsList:
1402 194 storres
                print "\t", specificRootResultsList[0],
1403 194 storres
                if len(specificRootResultsList) > 1:
1404 194 storres
                    print specificRootResultsList[1],
1405 194 storres
        print ; print
1406 194 storres
    #print globalResultsList
1407 194 storres
    #
1408 194 storres
    print "Timers and counters"
1409 194 storres
    print
1410 194 storres
    print "Number of iterations:", iterCount
1411 194 storres
    print "Taylor condition failures:", taylCondFailedCount
1412 194 storres
    print "Coppersmith condition failures:", coppCondFailedCount
1413 194 storres
    print "Resultant condition failures:", resultCondFailedCount
1414 194 storres
    print "Iterations count: ", iterCount
1415 194 storres
    print "Number of intervals:", len(globalResultsList)
1416 194 storres
    print "Number of basis constructions:", basisConstructionsCount
1417 194 storres
    print "Total CPU time spent in basis constructions:", \
1418 194 storres
        basisConstructionsFullTime
1419 194 storres
    if basisConstructionsCount != 0:
1420 194 storres
        print "Average basis construction CPU time:", \
1421 194 storres
            basisConstructionsFullTime/basisConstructionsCount
1422 194 storres
    print "Number of reductions:", reductionsCount
1423 194 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
1424 194 storres
    if reductionsCount != 0:
1425 194 storres
        print "Average reduction CPU time:", \
1426 194 storres
            reductionsFullTime/reductionsCount
1427 194 storres
    print "Number of resultants computation rounds:", \
1428 194 storres
        resultantsComputationsCount
1429 194 storres
    print "Total CPU time spent in resultants computation rounds:", \
1430 194 storres
        resultantsComputationsFullTime
1431 194 storres
    if resultantsComputationsCount != 0:
1432 194 storres
        print "Average resultants computation round CPU time:", \
1433 194 storres
            resultantsComputationsFullTime/resultantsComputationsCount
1434 194 storres
    print "Number of root finding rounds:", rootsComputationsCount
1435 194 storres
    print "Total CPU time spent in roots finding rounds:", \
1436 194 storres
        rootsComputationsFullTime
1437 194 storres
    if rootsComputationsCount != 0:
1438 194 storres
        print "Average roots finding round CPU time:", \
1439 194 storres
            rootsComputationsFullTime/rootsComputationsCount
1440 194 storres
    print "Global Wall time:", globalWallTime
1441 194 storres
    print "Global CPU time:", globalCpuTime
1442 194 storres
    ## Output counters
1443 194 storres
# End srs_runSLZ-v02
1444 194 storres
1445 212 storres
def srs_run_SLZ_v03(inputFunction,
1446 212 storres
                    inputLowerBound,
1447 212 storres
                    inputUpperBound,
1448 212 storres
                    alpha,
1449 212 storres
                    degree,
1450 212 storres
                    precision,
1451 212 storres
                    emin,
1452 212 storres
                    emax,
1453 212 storres
                    targetHardnessToRound,
1454 212 storres
                    debug = False):
1455 212 storres
    """
1456 212 storres
    Changes from V2:
1457 212 storres
        Root search is changed:
1458 212 storres
            - we compute the resultants in i and in t;
1459 212 storres
            - we compute the roots set of each of these resultants;
1460 212 storres
            - we combine all the possible pairs between the two sets;
1461 212 storres
            - we check these pairs in polynomials for correctness.
1462 212 storres
    Changes from V1:
1463 212 storres
        1- check for roots as soon as a resultant is computed;
1464 212 storres
        2- once a non null resultant is found, check for roots;
1465 212 storres
        3- constant resultant == no root.
1466 212 storres
    """
1467 212 storres
1468 212 storres
    if debug:
1469 212 storres
        print "Function                :", inputFunction
1470 212 storres
        print "Lower bound             :", inputLowerBound
1471 212 storres
        print "Upper bounds            :", inputUpperBound
1472 212 storres
        print "Alpha                   :", alpha
1473 212 storres
        print "Degree                  :", degree
1474 212 storres
        print "Precision               :", precision
1475 212 storres
        print "Emin                    :", emin
1476 212 storres
        print "Emax                    :", emax
1477 212 storres
        print "Target hardness-to-round:", targetHardnessToRound
1478 212 storres
        print
1479 212 storres
    ## Important constants.
1480 212 storres
    ### Stretch the interval if no error happens.
1481 212 storres
    noErrorIntervalStretch = 1 + 2^(-5)
1482 212 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
1483 212 storres
    #   by the following factor.
1484 212 storres
    noCoppersmithIntervalShrink = 1/2
1485 212 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
1486 212 storres
    #   shrink the interval by the following factor.
1487 212 storres
    oneCoppersmithIntervalShrink = 3/4
1488 212 storres
    #### If only null resultants are found, shrink the interval by the
1489 212 storres
    #    following factor.
1490 212 storres
    onlyNullResultantsShrink     = 3/4
1491 212 storres
    ## Structures.
1492 212 storres
    RRR         = RealField(precision)
1493 212 storres
    RRIF        = RealIntervalField(precision)
1494 212 storres
    ## Converting input bound into the "right" field.
1495 212 storres
    lowerBound = RRR(inputLowerBound)
1496 212 storres
    upperBound = RRR(inputUpperBound)
1497 212 storres
    ## Before going any further, check domain and image binade conditions.
1498 212 storres
    print inputFunction(1).n()
1499 212 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
1500 212 storres
    if output is None:
1501 212 storres
        print "Invalid domain/image binades. Domain:",\
1502 212 storres
        lowerBound, upperBound, "Images:", \
1503 212 storres
        inputFunction(lowerBound), inputFunction(upperBound)
1504 212 storres
        raise Exception("Invalid domain/image binades.")
1505 212 storres
    lb = output[0] ; ub = output[1]
1506 212 storres
    if lb != lowerBound or ub != upperBound:
1507 212 storres
        print "lb:", lb, " - ub:", ub
1508 212 storres
        print "Invalid domain/image binades. Domain:",\
1509 212 storres
        lowerBound, upperBound, "Images:", \
1510 212 storres
        inputFunction(lowerBound), inputFunction(upperBound)
1511 212 storres
        raise Exception("Invalid domain/image binades.")
1512 212 storres
    #
1513 212 storres
    ## Progam initialization
1514 212 storres
    ### Approximation polynomial accuracy and hardness to round.
1515 212 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
1516 212 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
1517 212 storres
    ### Significand to integer conversion ratio.
1518 212 storres
    toIntegerFactor           = 2^(precision-1)
1519 212 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
1520 212 storres
    ### Variables and rings for polynomials and root searching.
1521 212 storres
    i=var('i')
1522 212 storres
    t=var('t')
1523 212 storres
    inputFunctionVariable = inputFunction.variables()[0]
1524 212 storres
    function = inputFunction.subs({inputFunctionVariable:i})
1525 212 storres
    #  Polynomial Rings over the integers, for root finding.
1526 212 storres
    Zi = ZZ[i]
1527 212 storres
    Zt = ZZ[t]
1528 212 storres
    Zit = ZZ[i,t]
1529 212 storres
    ## Number of iterations limit.
1530 212 storres
    maxIter = 100000
1531 212 storres
    #
1532 212 storres
    ## Compute the scaled function and the degree, in their Sollya version
1533 212 storres
    #  once for all.
1534 212 storres
    (scaledf, sdlb, sdub, silb, siub) = \
1535 212 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
1536 212 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
1537 212 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
1538 212 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
1539 212 storres
    #
1540 212 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
1541 212 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
1542 212 storres
    (unscalingFunction, scalingFunction) = \
1543 212 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
1544 212 storres
    #print scalingFunction, unscalingFunction
1545 212 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
1546 212 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
1547 212 storres
    if internalSollyaPrec < 192:
1548 212 storres
        internalSollyaPrec = 192
1549 212 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
1550 212 storres
    print "Sollya internal precision:", internalSollyaPrec
1551 212 storres
    ## Some variables.
1552 212 storres
    ### General variables
1553 212 storres
    lb                  = sdlb
1554 212 storres
    ub                  = sdub
1555 212 storres
    nbw                 = 0
1556 212 storres
    intervalUlp         = ub.ulp()
1557 212 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
1558 212 storres
    ic                  = 0
1559 212 storres
    icAsInt             = 0    # Set from ic.
1560 212 storres
    solutionsSet        = set()
1561 212 storres
    tsErrorWidth        = []
1562 212 storres
    csErrorVectors      = []
1563 212 storres
    csVectorsResultants = []
1564 212 storres
    floatP              = 0  # Taylor polynomial.
1565 212 storres
    floatPcv            = 0  # Ditto with variable change.
1566 212 storres
    intvl               = "" # Taylor interval
1567 212 storres
    terr                = 0  # Taylor error.
1568 212 storres
    iterCount = 0
1569 212 storres
    htrnSet = set()
1570 212 storres
    ### Timers and counters.
1571 212 storres
    wallTimeStart                   = 0
1572 212 storres
    cpuTimeStart                    = 0
1573 212 storres
    taylCondFailedCount             = 0
1574 212 storres
    coppCondFailedCount             = 0
1575 212 storres
    resultCondFailedCount           = 0
1576 212 storres
    coppCondFailed                  = False
1577 212 storres
    resultCondFailed                = False
1578 212 storres
    globalResultsList               = []
1579 212 storres
    basisConstructionsCount         = 0
1580 212 storres
    basisConstructionsFullTime      = 0
1581 212 storres
    basisConstructionTime           = 0
1582 212 storres
    reductionsCount                 = 0
1583 212 storres
    reductionsFullTime              = 0
1584 212 storres
    reductionTime                   = 0
1585 212 storres
    resultantsComputationsCount     = 0
1586 212 storres
    resultantsComputationsFullTime  = 0
1587 212 storres
    resultantsComputationTime       = 0
1588 212 storres
    rootsComputationsCount          = 0
1589 212 storres
    rootsComputationsFullTime       = 0
1590 212 storres
    rootsComputationTime            = 0
1591 212 storres
    print
1592 212 storres
    ## Global times are started here.
1593 212 storres
    wallTimeStart                   = walltime()
1594 212 storres
    cpuTimeStart                    = cputime()
1595 212 storres
    ## Main loop.
1596 212 storres
    while True:
1597 212 storres
        if lb >= sdub:
1598 212 storres
            print "Lower bound reached upper bound."
1599 212 storres
            break
1600 212 storres
        if iterCount == maxIter:
1601 212 storres
            print "Reached maxIter. Aborting"
1602 212 storres
            break
1603 212 storres
        iterCount += 1
1604 212 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
1605 212 storres
            "log2(numbers)."
1606 212 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
1607 212 storres
        prceSo = slz_compute_polynomial_and_interval(scaledfSo,
1608 212 storres
                                                     degreeSo,
1609 212 storres
                                                     lb,
1610 212 storres
                                                     ub,
1611 212 storres
                                                     polyApproxAccur)
1612 212 storres
        ### Convert back the data into Sage space.
1613 212 storres
        (floatP, floatPcv, intvl, ic, terr) = \
1614 212 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
1615 212 storres
                                                 prceSo[1], prceSo[2],
1616 212 storres
                                                 prceSo[3]))
1617 212 storres
        intvl = RRIF(intvl)
1618 212 storres
        ## Clean-up Sollya stuff.
1619 212 storres
        for elem in prceSo:
1620 212 storres
            sollya_lib_clear_obj(elem)
1621 212 storres
        #print  floatP, floatPcv, intvl, ic, terr
1622 212 storres
        #print floatP
1623 212 storres
        #print intvl.endpoints()[0].n(), \
1624 212 storres
        #      ic.n(),
1625 212 storres
        #intvl.endpoints()[1].n()
1626 212 storres
        ### Check returned data.
1627 212 storres
        #### Is approximation error OK?
1628 212 storres
        if terr > polyApproxAccur:
1629 212 storres
            exceptionErrorMess  = \
1630 212 storres
                "Approximation failed - computed error:" + \
1631 212 storres
                str(terr) + " - target error: "
1632 212 storres
            exceptionErrorMess += \
1633 212 storres
                str(polyApproxAccur) + ". Aborting!"
1634 212 storres
            raise Exception(exceptionErrorMess)
1635 212 storres
        #### Is lower bound OK?
1636 212 storres
        if lb != intvl.endpoints()[0]:
1637 212 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
1638 212 storres
                               str(lb) + ". Aborting!"
1639 212 storres
            raise Exception(exceptionErrorMess)
1640 212 storres
        #### Set upper bound.
1641 212 storres
        if ub > intvl.endpoints()[1]:
1642 212 storres
            ub = intvl.endpoints()[1]
1643 212 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
1644 212 storres
            "log2(numbers)."
1645 212 storres
            taylCondFailedCount += 1
1646 212 storres
        #### Is interval not degenerate?
1647 212 storres
        if lb >= ub:
1648 212 storres
            exceptionErrorMess = "Degenerate interval: " + \
1649 212 storres
                                "lowerBound(" + str(lb) +\
1650 212 storres
                                ")>= upperBound(" + str(ub) + \
1651 212 storres
                                "). Aborting!"
1652 212 storres
            raise Exception(exceptionErrorMess)
1653 212 storres
        #### Is interval center ok?
1654 212 storres
        if ic <= lb or ic >= ub:
1655 212 storres
            exceptionErrorMess =  "Invalid interval center for " + \
1656 212 storres
                                str(lb) + ',' + str(ic) + ',' +  \
1657 212 storres
                                str(ub) + ". Aborting!"
1658 212 storres
            raise Exception(exceptionErrorMess)
1659 212 storres
        ##### Current interval width and reset future interval width.
1660 212 storres
        bw = ub - lb
1661 212 storres
        nbw = 0
1662 212 storres
        icAsInt = int(ic * toIntegerFactor)
1663 212 storres
        #### The following ratio is always >= 1. In case we may want to
1664 212 storres
        #    enlarge the interval
1665 212 storres
        curTaylErrRat = polyApproxAccur / terr
1666 212 storres
        ### Make the  integral transformations.
1667 212 storres
        #### Bounds and interval center.
1668 212 storres
        intIc = int(ic * toIntegerFactor)
1669 212 storres
        intLb = int(lb * toIntegerFactor) - intIc
1670 212 storres
        intUb = int(ub * toIntegerFactor) - intIc
1671 212 storres
        #
1672 212 storres
        #### Polynomials
1673 212 storres
        basisConstructionTime         = cputime()
1674 212 storres
        ##### To a polynomial with rational coefficients with rational arguments
1675 212 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
1676 212 storres
        ##### To a polynomial with rational coefficients with integer arguments
1677 212 storres
        ratIntP = \
1678 212 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
1679 212 storres
        #####  Ultimately a multivariate polynomial with integer coefficients
1680 212 storres
        #      with integer arguments.
1681 212 storres
        coppersmithTuple = \
1682 212 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
1683 212 storres
                                                        precision,
1684 212 storres
                                                        targetHardnessToRound,
1685 212 storres
                                                        i, t)
1686 212 storres
        #### Recover Coppersmith information.
1687 212 storres
        intIntP = coppersmithTuple[0]
1688 212 storres
        N = coppersmithTuple[1]
1689 212 storres
        nAtAlpha = N^alpha
1690 212 storres
        tBound = coppersmithTuple[2]
1691 212 storres
        leastCommonMultiple = coppersmithTuple[3]
1692 212 storres
        iBound = max(abs(intLb),abs(intUb))
1693 212 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
1694 212 storres
        basisConstructionsCount           += 1
1695 212 storres
        reductionTime                     = cputime()
1696 212 storres
        #### Compute the reduced polynomials.
1697 212 storres
        ccReducedPolynomialsList =  \
1698 212 storres
                slz_compute_coppersmith_reduced_polynomials(intIntP,
1699 212 storres
                                                            alpha,
1700 212 storres
                                                            N,
1701 212 storres
                                                            iBound,
1702 212 storres
                                                            tBound)
1703 212 storres
        if ccReducedPolynomialsList is None:
1704 212 storres
            raise Exception("Reduction failed.")
1705 212 storres
        reductionsFullTime    += cputime(reductionTime)
1706 212 storres
        reductionsCount       += 1
1707 212 storres
        if len(ccReducedPolynomialsList) < 2:
1708 212 storres
            print "Nothing to form resultants with."
1709 212 storres
            print
1710 212 storres
            coppCondFailedCount += 1
1711 212 storres
            coppCondFailed = True
1712 212 storres
            ##### Apply a different shrink factor according to
1713 212 storres
            #  the number of compliant polynomials.
1714 212 storres
            if len(ccReducedPolynomialsList) == 0:
1715 212 storres
                ub = lb + bw * noCoppersmithIntervalShrink
1716 212 storres
            else: # At least one compliant polynomial.
1717 212 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
1718 212 storres
            if ub > sdub:
1719 212 storres
                ub = sdub
1720 212 storres
            if lb == ub:
1721 212 storres
                raise Exception("Cant shrink interval \
1722 212 storres
                anymore to get Coppersmith condition.")
1723 212 storres
            nbw = 0
1724 212 storres
            continue
1725 212 storres
        #### We have at least two polynomials.
1726 212 storres
        #    Let us try to compute resultants.
1727 212 storres
        #    For each resultant computed, go for the solutions.
1728 212 storres
        ##### Build the pairs list.
1729 212 storres
        polyPairsList           = []
1730 212 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
1731 212 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
1732 212 storres
                                         len(ccReducedPolynomialsList)):
1733 212 storres
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
1734 212 storres
                                      ccReducedPolynomialsList[polyInnerIndex]))
1735 212 storres
        #### Actual root search.
1736 212 storres
        rootsSet            = set()
1737 212 storres
        hasNonNullResultant = False
1738 212 storres
        for polyPair in polyPairsList:
1739 212 storres
            if hasNonNullResultant:
1740 212 storres
                break
1741 212 storres
            resultantsComputationTime   = cputime()
1742 212 storres
            currentResultantI = \
1743 212 storres
                slz_resultant(polyPair[0],
1744 212 storres
                              polyPair[1],
1745 212 storres
                              t)
1746 212 storres
            resultantsComputationsCount    += 1
1747 212 storres
            if currentResultantI is None:
1748 212 storres
                resultantsComputationsFullTime +=  \
1749 212 storres
                    cputime(resultantsComputationTime)
1750 212 storres
                print "Nul resultant"
1751 212 storres
                continue # Next polyPair.
1752 212 storres
            currentResultantT = \
1753 212 storres
                slz_resultant(polyPair[0],
1754 212 storres
                              polyPair[1],
1755 212 storres
                              i)
1756 212 storres
            resultantsComputationsFullTime += cputime(resultantsComputationTime)
1757 212 storres
            resultantsComputationsCount    += 1
1758 212 storres
            if currentResultantT is None:
1759 212 storres
                print "Nul resultant"
1760 212 storres
                continue # Next polyPair.
1761 212 storres
            else:
1762 212 storres
                hasNonNullResultant = True
1763 212 storres
            #### We have a non null resultants pair. From now on, whatever the
1764 212 storres
            #    root search yields, no extra root search is necessary.
1765 212 storres
            #### A constant resultant leads to no root. Root search is done.
1766 212 storres
            if currentResultantI.degree() < 1:
1767 212 storres
                print "Resultant is constant:", currentResultantI
1768 212 storres
                break # Next polyPair and should break.
1769 212 storres
            if currentResultantT.degree() < 1:
1770 212 storres
                print "Resultant is constant:", currentResultantT
1771 212 storres
                break # Next polyPair and should break.
1772 212 storres
            #### Actual roots computation.
1773 212 storres
            rootsComputationTime       = cputime()
1774 212 storres
            ##### Compute i roots
1775 212 storres
            iRootsList = Zi(currentResultantI).roots()
1776 212 storres
            rootsComputationsCount      +=  1
1777 212 storres
            if len(iRootsList) == 0:
1778 212 storres
                rootsComputationsFullTime   =   cputime(rootsComputationTime)
1779 212 storres
                print "No roots in \"i\"."
1780 212 storres
                break # No roots in i.
1781 212 storres
            tRootsList = Zt(currentResultantT).roots()
1782 212 storres
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
1783 212 storres
            rootsComputationsCount      +=  1
1784 212 storres
            if len(tRootsList) == 0:
1785 212 storres
                print "No roots in \"t\"."
1786 212 storres
                break # No roots in i.
1787 212 storres
            ##### For each iRoot, get a tRoot and check against the polynomials.
1788 212 storres
            for iRoot in iRootsList:
1789 212 storres
                ####### Roots returned by roots() are (value, multiplicity)
1790 212 storres
                #       tuples.
1791 212 storres
                #print "iRoot:", iRoot
1792 212 storres
                for tRoot in tRootsList:
1793 212 storres
                ###### Use the tRoot against each polynomial, alternatively.
1794 212 storres
                    if polyPair[0](iRoot[0],tRoot[0]) != 0:
1795 212 storres
                        continue
1796 212 storres
                    if polyPair[1](iRoot[0],tRoot[0]) != 0:
1797 212 storres
                        continue
1798 212 storres
                    rootsSet.add((iRoot[0], tRoot[0]))
1799 212 storres
            # End of roots computation.
1800 212 storres
        # End loop for polyPair in polyParsList.  Will break at next iteration.
1801 212 storres
        # since a non null resultant was found.
1802 212 storres
        #### Prepare for results for the current interval..
1803 212 storres
        intervalResultsList = []
1804 212 storres
        intervalResultsList.append((lb, ub))
1805 212 storres
        #### Check roots.
1806 212 storres
        rootsResultsList = []
1807 212 storres
        for root in rootsSet:
1808 212 storres
            specificRootResultsList = []
1809 212 storres
            failingBounds = []
1810 212 storres
            intIntPdivN = intIntP(root[0], root[1]) / N
1811 212 storres
            if int(intIntPdivN) != intIntPdivN:
1812 212 storres
                continue # Next root
1813 212 storres
            # Root qualifies for modular equation, test it for hardness to round.
1814 212 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + root[0]) / toIntegerFactor)
1815 212 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
1816 212 storres
            #print scalingFunction
1817 212 storres
            scaledHardToRoundCaseAsFloat = \
1818 212 storres
                scalingFunction(hardToRoundCaseAsFloat)
1819 212 storres
            print "Candidate HTRNc at x =", \
1820 212 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
1821 212 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
1822 212 storres
                           function,
1823 212 storres
                           2^-(targetHardnessToRound),
1824 212 storres
                           RRR):
1825 212 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
1826 212 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
1827 212 storres
                    print "Found in interval."
1828 212 storres
                else:
1829 212 storres
                    print "Found out of interval."
1830 212 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
1831 212 storres
                # Check the root is in the bounds
1832 212 storres
                if abs(root[0]) > iBound or abs(root[1]) > tBound:
1833 212 storres
                    print "Root", root, "is out of bounds for modular equation."
1834 212 storres
                    if abs(root[0]) > iBound:
1835 212 storres
                        print "root[0]:", root[0]
1836 212 storres
                        print "i bound:", iBound
1837 212 storres
                        failingBounds.append('i')
1838 212 storres
                        failingBounds.append(root[0])
1839 212 storres
                        failingBounds.append(iBound)
1840 212 storres
                    if abs(root[1]) > tBound:
1841 212 storres
                        print "root[1]:", root[1]
1842 212 storres
                        print "t bound:", tBound
1843 212 storres
                        failingBounds.append('t')
1844 212 storres
                        failingBounds.append(root[1])
1845 212 storres
                        failingBounds.append(tBound)
1846 212 storres
                if len(failingBounds) > 0:
1847 212 storres
                    specificRootResultsList.append(failingBounds)
1848 212 storres
            else: # From slz_is_htrn...
1849 212 storres
                print "is not an HTRN case."
1850 212 storres
            if len(specificRootResultsList) > 0:
1851 212 storres
                rootsResultsList.append(specificRootResultsList)
1852 212 storres
        if len(rootsResultsList) > 0:
1853 212 storres
            intervalResultsList.append(rootsResultsList)
1854 212 storres
        ### Check if a non null resultant was found. If not shrink the interval.
1855 212 storres
        if not hasNonNullResultant:
1856 212 storres
            print "Only null resultants for this reduction, shrinking interval."
1857 212 storres
            resultCondFailed      =  True
1858 212 storres
            resultCondFailedCount += 1
1859 212 storres
            ### Shrink interval for next iteration.
1860 212 storres
            ub = lb + bw * onlyNullResultantsShrink
1861 212 storres
            if ub > sdub:
1862 212 storres
                ub = sdub
1863 212 storres
            nbw = 0
1864 212 storres
            continue
1865 212 storres
        #### An intervalResultsList has at least the bounds.
1866 212 storres
        globalResultsList.append(intervalResultsList)
1867 212 storres
        #### Compute an incremented width for next upper bound, only
1868 212 storres
        #    if not Coppersmith condition nor resultant condition
1869 212 storres
        #    failed at the previous run.
1870 212 storres
        if not coppCondFailed and not resultCondFailed:
1871 212 storres
            nbw = noErrorIntervalStretch * bw
1872 212 storres
        else:
1873 212 storres
            nbw = bw
1874 212 storres
        ##### Reset the failure flags. They will be raised
1875 212 storres
        #     again if needed.
1876 212 storres
        coppCondFailed   = False
1877 212 storres
        resultCondFailed = False
1878 212 storres
        #### For next iteration (at end of loop)
1879 212 storres
        #print "nbw:", nbw
1880 212 storres
        lb  = ub
1881 212 storres
        ub += nbw
1882 212 storres
        if ub > sdub:
1883 212 storres
            ub = sdub
1884 212 storres
        print
1885 212 storres
    # End while True
1886 212 storres
    ## Main loop just ended.
1887 212 storres
    globalWallTime = walltime(wallTimeStart)
1888 212 storres
    globalCpuTime  = cputime(cpuTimeStart)
1889 212 storres
    ## Output results
1890 212 storres
    print ; print "Intervals and HTRNs" ; print
1891 212 storres
    for intervalResultsList in globalResultsList:
1892 212 storres
        print "[", intervalResultsList[0][0], ",",intervalResultsList[0][1], "]",
1893 212 storres
        if len(intervalResultsList) > 1:
1894 212 storres
            rootsResultsList = intervalResultsList[1]
1895 212 storres
            for specificRootResultsList in rootsResultsList:
1896 212 storres
                print "\t", specificRootResultsList[0],
1897 212 storres
                if len(specificRootResultsList) > 1:
1898 212 storres
                    print specificRootResultsList[1],
1899 212 storres
        print ; print
1900 212 storres
    #print globalResultsList
1901 212 storres
    #
1902 212 storres
    print "Timers and counters"
1903 212 storres
    print
1904 212 storres
    print "Number of iterations:", iterCount
1905 212 storres
    print "Taylor condition failures:", taylCondFailedCount
1906 212 storres
    print "Coppersmith condition failures:", coppCondFailedCount
1907 212 storres
    print "Resultant condition failures:", resultCondFailedCount
1908 212 storres
    print "Iterations count: ", iterCount
1909 212 storres
    print "Number of intervals:", len(globalResultsList)
1910 212 storres
    print "Number of basis constructions:", basisConstructionsCount
1911 212 storres
    print "Total CPU time spent in basis constructions:", \
1912 212 storres
        basisConstructionsFullTime
1913 212 storres
    if basisConstructionsCount != 0:
1914 212 storres
        print "Average basis construction CPU time:", \
1915 212 storres
            basisConstructionsFullTime/basisConstructionsCount
1916 212 storres
    print "Number of reductions:", reductionsCount
1917 212 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
1918 212 storres
    if reductionsCount != 0:
1919 212 storres
        print "Average reduction CPU time:", \
1920 212 storres
            reductionsFullTime/reductionsCount
1921 212 storres
    print "Number of resultants computation rounds:", \
1922 212 storres
        resultantsComputationsCount
1923 212 storres
    print "Total CPU time spent in resultants computation rounds:", \
1924 212 storres
        resultantsComputationsFullTime
1925 212 storres
    if resultantsComputationsCount != 0:
1926 212 storres
        print "Average resultants computation round CPU time:", \
1927 212 storres
            resultantsComputationsFullTime/resultantsComputationsCount
1928 212 storres
    print "Number of root finding rounds:", rootsComputationsCount
1929 212 storres
    print "Total CPU time spent in roots finding rounds:", \
1930 212 storres
        rootsComputationsFullTime
1931 212 storres
    if rootsComputationsCount != 0:
1932 212 storres
        print "Average roots finding round CPU time:", \
1933 212 storres
            rootsComputationsFullTime/rootsComputationsCount
1934 212 storres
    print "Global Wall time:", globalWallTime
1935 212 storres
    print "Global CPU time:", globalCpuTime
1936 212 storres
    ## Output counters
1937 212 storres
# End srs_runSLZ-v03
1938 212 storres
1939 213 storres
def srs_run_SLZ_v04(inputFunction,
1940 212 storres
                    inputLowerBound,
1941 212 storres
                    inputUpperBound,
1942 212 storres
                    alpha,
1943 212 storres
                    degree,
1944 212 storres
                    precision,
1945 212 storres
                    emin,
1946 212 storres
                    emax,
1947 212 storres
                    targetHardnessToRound,
1948 212 storres
                    debug = False):
1949 212 storres
    """
1950 213 storres
    Changes from V3:
1951 213 storres
        Root search is changed again:
1952 213 storres
            - only resultants in i are computed;
1953 213 storres
            - root are searched for;
1954 213 storres
            - if any, they are tested for hardness-to-round.
1955 212 storres
    Changes from V2:
1956 212 storres
        Root search is changed:
1957 212 storres
            - we compute the resultants in i and in t;
1958 212 storres
            - we compute the roots set of each of these resultants;
1959 212 storres
            - we combine all the possible pairs between the two sets;
1960 212 storres
            - we check these pairs in polynomials for correctness.
1961 212 storres
    Changes from V1:
1962 212 storres
        1- check for roots as soon as a resultant is computed;
1963 212 storres
        2- once a non null resultant is found, check for roots;
1964 212 storres
        3- constant resultant == no root.
1965 212 storres
    """
1966 212 storres
1967 212 storres
    if debug:
1968 212 storres
        print "Function                :", inputFunction
1969 212 storres
        print "Lower bound             :", inputLowerBound
1970 212 storres
        print "Upper bounds            :", inputUpperBound
1971 212 storres
        print "Alpha                   :", alpha
1972 212 storres
        print "Degree                  :", degree
1973 212 storres
        print "Precision               :", precision
1974 212 storres
        print "Emin                    :", emin
1975 212 storres
        print "Emax                    :", emax
1976 212 storres
        print "Target hardness-to-round:", targetHardnessToRound
1977 212 storres
        print
1978 212 storres
    ## Important constants.
1979 212 storres
    ### Stretch the interval if no error happens.
1980 212 storres
    noErrorIntervalStretch = 1 + 2^(-5)
1981 212 storres
    ### If no vector validates the Coppersmith condition, shrink the interval
1982 212 storres
    #   by the following factor.
1983 212 storres
    noCoppersmithIntervalShrink = 1/2
1984 212 storres
    ### If only (or at least) one vector validates the Coppersmith condition,
1985 212 storres
    #   shrink the interval by the following factor.
1986 212 storres
    oneCoppersmithIntervalShrink = 3/4
1987 212 storres
    #### If only null resultants are found, shrink the interval by the
1988 212 storres
    #    following factor.
1989 212 storres
    onlyNullResultantsShrink     = 3/4
1990 212 storres
    ## Structures.
1991 212 storres
    RRR         = RealField(precision)
1992 212 storres
    RRIF        = RealIntervalField(precision)
1993 212 storres
    ## Converting input bound into the "right" field.
1994 212 storres
    lowerBound = RRR(inputLowerBound)
1995 212 storres
    upperBound = RRR(inputUpperBound)
1996 212 storres
    ## Before going any further, check domain and image binade conditions.
1997 212 storres
    print inputFunction(1).n()
1998 212 storres
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
1999 212 storres
    if output is None:
2000 212 storres
        print "Invalid domain/image binades. Domain:",\
2001 212 storres
        lowerBound, upperBound, "Images:", \
2002 212 storres
        inputFunction(lowerBound), inputFunction(upperBound)
2003 212 storres
        raise Exception("Invalid domain/image binades.")
2004 212 storres
    lb = output[0] ; ub = output[1]
2005 212 storres
    if lb != lowerBound or ub != upperBound:
2006 212 storres
        print "lb:", lb, " - ub:", ub
2007 212 storres
        print "Invalid domain/image binades. Domain:",\
2008 212 storres
        lowerBound, upperBound, "Images:", \
2009 212 storres
        inputFunction(lowerBound), inputFunction(upperBound)
2010 212 storres
        raise Exception("Invalid domain/image binades.")
2011 212 storres
    #
2012 212 storres
    ## Progam initialization
2013 212 storres
    ### Approximation polynomial accuracy and hardness to round.
2014 212 storres
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
2015 212 storres
    polyTargetHardnessToRound = targetHardnessToRound + 1
2016 212 storres
    ### Significand to integer conversion ratio.
2017 212 storres
    toIntegerFactor           = 2^(precision-1)
2018 212 storres
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
2019 212 storres
    ### Variables and rings for polynomials and root searching.
2020 212 storres
    i=var('i')
2021 212 storres
    t=var('t')
2022 212 storres
    inputFunctionVariable = inputFunction.variables()[0]
2023 212 storres
    function = inputFunction.subs({inputFunctionVariable:i})
2024 212 storres
    #  Polynomial Rings over the integers, for root finding.
2025 212 storres
    Zi = ZZ[i]
2026 212 storres
    Zt = ZZ[t]
2027 212 storres
    Zit = ZZ[i,t]
2028 212 storres
    ## Number of iterations limit.
2029 212 storres
    maxIter = 100000
2030 212 storres
    #
2031 212 storres
    ## Compute the scaled function and the degree, in their Sollya version
2032 212 storres
    #  once for all.
2033 212 storres
    (scaledf, sdlb, sdub, silb, siub) = \
2034 212 storres
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
2035 212 storres
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
2036 212 storres
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
2037 212 storres
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
2038 212 storres
    #
2039 212 storres
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
2040 212 storres
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
2041 212 storres
    (unscalingFunction, scalingFunction) = \
2042 212 storres
        slz_interval_scaling_expression(domainBoundsInterval, i)
2043 212 storres
    #print scalingFunction, unscalingFunction
2044 212 storres
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
2045 212 storres
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
2046 212 storres
    if internalSollyaPrec < 192:
2047 212 storres
        internalSollyaPrec = 192
2048 212 storres
    pobyso_set_prec_sa_so(internalSollyaPrec)
2049 212 storres
    print "Sollya internal precision:", internalSollyaPrec
2050 212 storres
    ## Some variables.
2051 212 storres
    ### General variables
2052 212 storres
    lb                  = sdlb
2053 212 storres
    ub                  = sdub
2054 212 storres
    nbw                 = 0
2055 212 storres
    intervalUlp         = ub.ulp()
2056 212 storres
    #### Will be set by slz_interval_and_polynomila_to_sage.
2057 212 storres
    ic                  = 0
2058 212 storres
    icAsInt             = 0    # Set from ic.
2059 212 storres
    solutionsSet        = set()
2060 212 storres
    tsErrorWidth        = []
2061 212 storres
    csErrorVectors      = []
2062 212 storres
    csVectorsResultants = []
2063 212 storres
    floatP              = 0  # Taylor polynomial.
2064 212 storres
    floatPcv            = 0  # Ditto with variable change.
2065 212 storres
    intvl               = "" # Taylor interval
2066 212 storres
    terr                = 0  # Taylor error.
2067 212 storres
    iterCount = 0
2068 212 storres
    htrnSet = set()
2069 212 storres
    ### Timers and counters.
2070 212 storres
    wallTimeStart                   = 0
2071 212 storres
    cpuTimeStart                    = 0
2072 212 storres
    taylCondFailedCount             = 0
2073 212 storres
    coppCondFailedCount             = 0
2074 212 storres
    resultCondFailedCount           = 0
2075 212 storres
    coppCondFailed                  = False
2076 212 storres
    resultCondFailed                = False
2077 212 storres
    globalResultsList               = []
2078 212 storres
    basisConstructionsCount         = 0
2079 212 storres
    basisConstructionsFullTime      = 0
2080 212 storres
    basisConstructionTime           = 0
2081 212 storres
    reductionsCount                 = 0
2082 212 storres
    reductionsFullTime              = 0
2083 212 storres
    reductionTime                   = 0
2084 212 storres
    resultantsComputationsCount     = 0
2085 212 storres
    resultantsComputationsFullTime  = 0
2086 212 storres
    resultantsComputationTime       = 0
2087 212 storres
    rootsComputationsCount          = 0
2088 212 storres
    rootsComputationsFullTime       = 0
2089 212 storres
    rootsComputationTime            = 0
2090 212 storres
    print
2091 212 storres
    ## Global times are started here.
2092 212 storres
    wallTimeStart                   = walltime()
2093 212 storres
    cpuTimeStart                    = cputime()
2094 212 storres
    ## Main loop.
2095 212 storres
    while True:
2096 212 storres
        if lb >= sdub:
2097 212 storres
            print "Lower bound reached upper bound."
2098 212 storres
            break
2099 212 storres
        if iterCount == maxIter:
2100 212 storres
            print "Reached maxIter. Aborting"
2101 212 storres
            break
2102 212 storres
        iterCount += 1
2103 212 storres
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
2104 212 storres
            "log2(numbers)."
2105 212 storres
        ### Compute a Sollya polynomial that will honor the Taylor condition.
2106 212 storres
        prceSo = slz_compute_polynomial_and_interval(scaledfSo,
2107 212 storres
                                                     degreeSo,
2108 212 storres
                                                     lb,
2109 212 storres
                                                     ub,
2110 212 storres
                                                     polyApproxAccur)
2111 212 storres
        ### Convert back the data into Sage space.
2112 212 storres
        (floatP, floatPcv, intvl, ic, terr) = \
2113 212 storres
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
2114 212 storres
                                                 prceSo[1], prceSo[2],
2115 212 storres
                                                 prceSo[3]))
2116 212 storres
        intvl = RRIF(intvl)
2117 212 storres
        ## Clean-up Sollya stuff.
2118 212 storres
        for elem in prceSo:
2119 212 storres
            sollya_lib_clear_obj(elem)
2120 212 storres
        #print  floatP, floatPcv, intvl, ic, terr
2121 212 storres
        #print floatP
2122 212 storres
        #print intvl.endpoints()[0].n(), \
2123 212 storres
        #      ic.n(),
2124 212 storres
        #intvl.endpoints()[1].n()
2125 212 storres
        ### Check returned data.
2126 212 storres
        #### Is approximation error OK?
2127 212 storres
        if terr > polyApproxAccur:
2128 212 storres
            exceptionErrorMess  = \
2129 212 storres
                "Approximation failed - computed error:" + \
2130 212 storres
                str(terr) + " - target error: "
2131 212 storres
            exceptionErrorMess += \
2132 212 storres
                str(polyApproxAccur) + ". Aborting!"
2133 212 storres
            raise Exception(exceptionErrorMess)
2134 212 storres
        #### Is lower bound OK?
2135 212 storres
        if lb != intvl.endpoints()[0]:
2136 212 storres
            exceptionErrorMess =  "Wrong lower bound:" + \
2137 212 storres
                               str(lb) + ". Aborting!"
2138 212 storres
            raise Exception(exceptionErrorMess)
2139 212 storres
        #### Set upper bound.
2140 212 storres
        if ub > intvl.endpoints()[1]:
2141 212 storres
            ub = intvl.endpoints()[1]
2142 212 storres
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
2143 212 storres
            "log2(numbers)."
2144 212 storres
            taylCondFailedCount += 1
2145 212 storres
        #### Is interval not degenerate?
2146 212 storres
        if lb >= ub:
2147 212 storres
            exceptionErrorMess = "Degenerate interval: " + \
2148 212 storres
                                "lowerBound(" + str(lb) +\
2149 212 storres
                                ")>= upperBound(" + str(ub) + \
2150 212 storres
                                "). Aborting!"
2151 212 storres
            raise Exception(exceptionErrorMess)
2152 212 storres
        #### Is interval center ok?
2153 212 storres
        if ic <= lb or ic >= ub:
2154 212 storres
            exceptionErrorMess =  "Invalid interval center for " + \
2155 212 storres
                                str(lb) + ',' + str(ic) + ',' +  \
2156 212 storres
                                str(ub) + ". Aborting!"
2157 212 storres
            raise Exception(exceptionErrorMess)
2158 212 storres
        ##### Current interval width and reset future interval width.
2159 212 storres
        bw = ub - lb
2160 212 storres
        nbw = 0
2161 212 storres
        icAsInt = int(ic * toIntegerFactor)
2162 212 storres
        #### The following ratio is always >= 1. In case we may want to
2163 212 storres
        #    enlarge the interval
2164 212 storres
        curTaylErrRat = polyApproxAccur / terr
2165 212 storres
        ### Make the  integral transformations.
2166 212 storres
        #### Bounds and interval center.
2167 212 storres
        intIc = int(ic * toIntegerFactor)
2168 212 storres
        intLb = int(lb * toIntegerFactor) - intIc
2169 212 storres
        intUb = int(ub * toIntegerFactor) - intIc
2170 212 storres
        #
2171 212 storres
        #### Polynomials
2172 212 storres
        basisConstructionTime         = cputime()
2173 212 storres
        ##### To a polynomial with rational coefficients with rational arguments
2174 212 storres
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
2175 212 storres
        ##### To a polynomial with rational coefficients with integer arguments
2176 212 storres
        ratIntP = \
2177 212 storres
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
2178 212 storres
        #####  Ultimately a multivariate polynomial with integer coefficients
2179 212 storres
        #      with integer arguments.
2180 212 storres
        coppersmithTuple = \
2181 212 storres
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP,
2182 212 storres
                                                        precision,
2183 212 storres
                                                        targetHardnessToRound,
2184 212 storres
                                                        i, t)
2185 212 storres
        #### Recover Coppersmith information.
2186 212 storres
        intIntP = coppersmithTuple[0]
2187 212 storres
        N = coppersmithTuple[1]
2188 212 storres
        nAtAlpha = N^alpha
2189 212 storres
        tBound = coppersmithTuple[2]
2190 212 storres
        leastCommonMultiple = coppersmithTuple[3]
2191 212 storres
        iBound = max(abs(intLb),abs(intUb))
2192 212 storres
        basisConstructionsFullTime        += cputime(basisConstructionTime)
2193 212 storres
        basisConstructionsCount           += 1
2194 212 storres
        reductionTime                     = cputime()
2195 212 storres
        #### Compute the reduced polynomials.
2196 212 storres
        ccReducedPolynomialsList =  \
2197 213 storres
                slz_compute_coppersmith_reduced_polynomials(intIntP,
2198 213 storres
                                                            alpha,
2199 213 storres
                                                            N,
2200 213 storres
                                                            iBound,
2201 213 storres
                                                            tBound)
2202 212 storres
        if ccReducedPolynomialsList is None:
2203 212 storres
            raise Exception("Reduction failed.")
2204 212 storres
        reductionsFullTime    += cputime(reductionTime)
2205 212 storres
        reductionsCount       += 1
2206 212 storres
        if len(ccReducedPolynomialsList) < 2:
2207 212 storres
            print "Nothing to form resultants with."
2208 212 storres
            print
2209 212 storres
            coppCondFailedCount += 1
2210 212 storres
            coppCondFailed = True
2211 212 storres
            ##### Apply a different shrink factor according to
2212 212 storres
            #  the number of compliant polynomials.
2213 212 storres
            if len(ccReducedPolynomialsList) == 0:
2214 212 storres
                ub = lb + bw * noCoppersmithIntervalShrink
2215 212 storres
            else: # At least one compliant polynomial.
2216 212 storres
                ub = lb + bw * oneCoppersmithIntervalShrink
2217 212 storres
            if ub > sdub:
2218 212 storres
                ub = sdub
2219 212 storres
            if lb == ub:
2220 212 storres
                raise Exception("Cant shrink interval \
2221 212 storres
                anymore to get Coppersmith condition.")
2222 212 storres
            nbw = 0
2223 212 storres
            continue
2224 212 storres
        #### We have at least two polynomials.
2225 212 storres
        #    Let us try to compute resultants.
2226 212 storres
        #    For each resultant computed, go for the solutions.
2227 212 storres
        ##### Build the pairs list.
2228 212 storres
        polyPairsList           = []
2229 212 storres
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
2230 212 storres
            for polyInnerIndex in xrange(polyOuterIndex+1,
2231 212 storres
                                         len(ccReducedPolynomialsList)):
2232 212 storres
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
2233 212 storres
                                      ccReducedPolynomialsList[polyInnerIndex]))
2234 212 storres
        #### Actual root search.
2235 213 storres
        iRootsSet           = set()
2236 212 storres
        hasNonNullResultant = False
2237 212 storres
        for polyPair in polyPairsList:
2238 212 storres
            resultantsComputationTime   = cputime()
2239 212 storres
            currentResultantI = \
2240 212 storres
                slz_resultant(polyPair[0],
2241 212 storres
                              polyPair[1],
2242 212 storres
                              t)
2243 212 storres
            resultantsComputationsCount    += 1
2244 213 storres
            resultantsComputationsFullTime +=  \
2245 213 storres
                cputime(resultantsComputationTime)
2246 213 storres
            #### Function slz_resultant returns None both for None and O
2247 213 storres
            #    resultants.
2248 212 storres
            if currentResultantI is None:
2249 212 storres
                print "Nul resultant"
2250 212 storres
                continue # Next polyPair.
2251 213 storres
            ## We deleted the currentResultantI computation.
2252 213 storres
            #### We have a non null resultant. From now on, whatever this
2253 212 storres
            #    root search yields, no extra root search is necessary.
2254 213 storres
            hasNonNullResultant = True
2255 212 storres
            #### A constant resultant leads to no root. Root search is done.
2256 212 storres
            if currentResultantI.degree() < 1:
2257 212 storres
                print "Resultant is constant:", currentResultantI
2258 213 storres
                break # There is no root.
2259 213 storres
            #### Actual iroots computation.
2260 213 storres
            rootsComputationTime        = cputime()
2261 212 storres
            iRootsList = Zi(currentResultantI).roots()
2262 212 storres
            rootsComputationsCount      +=  1
2263 213 storres
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
2264 212 storres
            if len(iRootsList) == 0:
2265 212 storres
                print "No roots in \"i\"."
2266 212 storres
                break # No roots in i.
2267 213 storres
            else:
2268 213 storres
                for iRoot in iRootsList:
2269 213 storres
                    # A root is given as a (value, multiplicity) tuple.
2270 213 storres
                    iRootsSet.add(iRoot[0])
2271 213 storres
        # End loop for polyPair in polyParsList. We only loop again if a
2272 213 storres
        # None or zero resultant is found.
2273 212 storres
        #### Prepare for results for the current interval..
2274 212 storres
        intervalResultsList = []
2275 212 storres
        intervalResultsList.append((lb, ub))
2276 212 storres
        #### Check roots.
2277 212 storres
        rootsResultsList = []
2278 213 storres
        for iRoot in iRootsSet:
2279 212 storres
            specificRootResultsList = []
2280 213 storres
            failingBounds           = []
2281 212 storres
            # Root qualifies for modular equation, test it for hardness to round.
2282 213 storres
            hardToRoundCaseAsFloat = RRR((icAsInt + iRoot) / toIntegerFactor)
2283 212 storres
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
2284 212 storres
            #print scalingFunction
2285 212 storres
            scaledHardToRoundCaseAsFloat = \
2286 212 storres
                scalingFunction(hardToRoundCaseAsFloat)
2287 212 storres
            print "Candidate HTRNc at x =", \
2288 212 storres
                scaledHardToRoundCaseAsFloat.n().str(base=2),
2289 212 storres
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
2290 212 storres
                           function,
2291 212 storres
                           2^-(targetHardnessToRound),
2292 212 storres
                           RRR):
2293 212 storres
                print hardToRoundCaseAsFloat, "is HTRN case."
2294 213 storres
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
2295 212 storres
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
2296 212 storres
                    print "Found in interval."
2297 212 storres
                else:
2298 212 storres
                    print "Found out of interval."
2299 213 storres
                # Check the i root is within the i bound.
2300 213 storres
                if abs(iRoot) > iBound:
2301 213 storres
                    print "IRoot", iRoot, "is out of bounds for modular equation."
2302 213 storres
                    print "i bound:", iBound
2303 213 storres
                    failingBounds.append('i')
2304 213 storres
                    failingBounds.append(iRoot)
2305 213 storres
                    failingBounds.append(iBound)
2306 212 storres
                if len(failingBounds) > 0:
2307 212 storres
                    specificRootResultsList.append(failingBounds)
2308 212 storres
            else: # From slz_is_htrn...
2309 212 storres
                print "is not an HTRN case."
2310 212 storres
            if len(specificRootResultsList) > 0:
2311 212 storres
                rootsResultsList.append(specificRootResultsList)
2312 212 storres
        if len(rootsResultsList) > 0:
2313 212 storres
            intervalResultsList.append(rootsResultsList)
2314 212 storres
        ### Check if a non null resultant was found. If not shrink the interval.
2315 212 storres
        if not hasNonNullResultant:
2316 212 storres
            print "Only null resultants for this reduction, shrinking interval."
2317 212 storres
            resultCondFailed      =  True
2318 212 storres
            resultCondFailedCount += 1
2319 212 storres
            ### Shrink interval for next iteration.
2320 212 storres
            ub = lb + bw * onlyNullResultantsShrink
2321 212 storres
            if ub > sdub:
2322 212 storres
                ub = sdub
2323 212 storres
            nbw = 0
2324 212 storres
            continue
2325 212 storres
        #### An intervalResultsList has at least the bounds.
2326 212 storres
        globalResultsList.append(intervalResultsList)
2327 212 storres
        #### Compute an incremented width for next upper bound, only
2328 212 storres
        #    if not Coppersmith condition nor resultant condition
2329 212 storres
        #    failed at the previous run.
2330 212 storres
        if not coppCondFailed and not resultCondFailed:
2331 212 storres
            nbw = noErrorIntervalStretch * bw
2332 212 storres
        else:
2333 212 storres
            nbw = bw
2334 212 storres
        ##### Reset the failure flags. They will be raised
2335 212 storres
        #     again if needed.
2336 212 storres
        coppCondFailed   = False
2337 212 storres
        resultCondFailed = False
2338 212 storres
        #### For next iteration (at end of loop)
2339 212 storres
        #print "nbw:", nbw
2340 212 storres
        lb  = ub
2341 212 storres
        ub += nbw
2342 212 storres
        if ub > sdub:
2343 212 storres
            ub = sdub
2344 212 storres
        print
2345 212 storres
    # End while True
2346 212 storres
    ## Main loop just ended.
2347 212 storres
    globalWallTime = walltime(wallTimeStart)
2348 212 storres
    globalCpuTime  = cputime(cpuTimeStart)
2349 212 storres
    ## Output results
2350 212 storres
    print ; print "Intervals and HTRNs" ; print
2351 212 storres
    for intervalResultsList in globalResultsList:
2352 212 storres
        print "[", intervalResultsList[0][0], ",",intervalResultsList[0][1], "]",
2353 212 storres
        if len(intervalResultsList) > 1:
2354 212 storres
            rootsResultsList = intervalResultsList[1]
2355 212 storres
            for specificRootResultsList in rootsResultsList:
2356 212 storres
                print "\t", specificRootResultsList[0],
2357 212 storres
                if len(specificRootResultsList) > 1:
2358 212 storres
                    print specificRootResultsList[1],
2359 212 storres
        print ; print
2360 212 storres
    #print globalResultsList
2361 212 storres
    #
2362 212 storres
    print "Timers and counters"
2363 212 storres
    print
2364 212 storres
    print "Number of iterations:", iterCount
2365 212 storres
    print "Taylor condition failures:", taylCondFailedCount
2366 212 storres
    print "Coppersmith condition failures:", coppCondFailedCount
2367 212 storres
    print "Resultant condition failures:", resultCondFailedCount
2368 212 storres
    print "Iterations count: ", iterCount
2369 212 storres
    print "Number of intervals:", len(globalResultsList)
2370 212 storres
    print "Number of basis constructions:", basisConstructionsCount
2371 212 storres
    print "Total CPU time spent in basis constructions:", \
2372 212 storres
        basisConstructionsFullTime
2373 212 storres
    if basisConstructionsCount != 0:
2374 212 storres
        print "Average basis construction CPU time:", \
2375 212 storres
            basisConstructionsFullTime/basisConstructionsCount
2376 212 storres
    print "Number of reductions:", reductionsCount
2377 212 storres
    print "Total CPU time spent in reductions:", reductionsFullTime
2378 212 storres
    if reductionsCount != 0:
2379 212 storres
        print "Average reduction CPU time:", \
2380 212 storres
            reductionsFullTime/reductionsCount
2381 212 storres
    print "Number of resultants computation rounds:", \
2382 212 storres
        resultantsComputationsCount
2383 212 storres
    print "Total CPU time spent in resultants computation rounds:", \
2384 212 storres
        resultantsComputationsFullTime
2385 212 storres
    if resultantsComputationsCount != 0:
2386 212 storres
        print "Average resultants computation round CPU time:", \
2387 212 storres
            resultantsComputationsFullTime/resultantsComputationsCount
2388 212 storres
    print "Number of root finding rounds:", rootsComputationsCount
2389 212 storres
    print "Total CPU time spent in roots finding rounds:", \
2390 212 storres
        rootsComputationsFullTime
2391 212 storres
    if rootsComputationsCount != 0:
2392 212 storres
        print "Average roots finding round CPU time:", \
2393 212 storres
            rootsComputationsFullTime/rootsComputationsCount
2394 212 storres
    print "Global Wall time:", globalWallTime
2395 212 storres
    print "Global CPU time:", globalCpuTime
2396 212 storres
    ## Output counters
2397 213 storres
# End srs_runSLZ-v04