Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (203,38 ko)

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