Statistiques
| Révision :

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

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