Statistiques
| Révision :

root / pobysoPythonSage / src / sageSLZ / sageSLZ.sage @ 94

Historique | Voir | Annoter | Télécharger (19,5 ko)

1 90 storres
"""
2 90 storres
module: sageSLZ.sage
3 90 storres
4 90 storres
Sage core function needed for the implementation of SLZ.
5 90 storres
6 90 storres
Created on 2013-08
7 90 storres
8 90 storres
moduleauthor:: S.T.
9 90 storres
"""
10 87 storres
print "sageSLZ loading..."
11 61 storres
def slz_compute_polynomial_and_interval(functionSo, degreeSo, lowerBoundSa,
12 61 storres
                                        upperBoundSa, approxPrecSa,
13 61 storres
                                        sollyaPrecSa=None):
14 61 storres
    """
15 61 storres
    Under the assumptions listed for slz_get_intervals_and_polynomials, compute
16 61 storres
    a polynomial that approximates the function on a an interval starting
17 61 storres
    at lowerBoundSa and finishing at a value that guarantees that the polynomial
18 61 storres
    approximates with the expected precision.
19 61 storres
    The interval upper bound is lowered until the expected approximation
20 61 storres
    precision is reached.
21 61 storres
    The polynomial, the bounds, the center of the interval and the error
22 61 storres
    are returned.
23 61 storres
    """
24 61 storres
    RRR = lowerBoundSa.parent()
25 61 storres
    intervalShrinkConstFactorSa = RRR('0.5')
26 61 storres
    absoluteErrorTypeSo = pobyso_absolute_so_so()
27 61 storres
    currentRangeSo = pobyso_bounds_to_range_sa_so(lowerBoundSa, upperBoundSa)
28 61 storres
    currentUpperBoundSa = upperBoundSa
29 61 storres
    currentLowerBoundSa = lowerBoundSa
30 61 storres
    # What we want here is the polynomial without the variable change,
31 61 storres
    # since our actual variable will be x-intervalCenter defined over the
32 61 storres
    # domain [lowerBound-intervalCenter , upperBound-intervalCenter].
33 61 storres
    (polySo, intervalCenterSo, maxErrorSo) = \
34 61 storres
        pobyso_taylor_expansion_no_change_var_so_so(functionSo, degreeSo,
35 61 storres
                                                    currentRangeSo,
36 61 storres
                                                    absoluteErrorTypeSo)
37 61 storres
    maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
38 61 storres
    while maxErrorSa > approxPrecSa:
39 61 storres
        sollya_lib_clear_obj(maxErrorSo)
40 81 storres
        sollya_lib_clear_obj(polySo)
41 81 storres
        sollya_lib_clear_obj(intervalCenterSo)
42 81 storres
        shrinkFactorSa = RRR('5.0')/(maxErrorSa/approxPrecSa).log2().abs()
43 81 storres
        #shrinkFactorSa = 1.5/(maxErrorSa/approxPrecSa)
44 81 storres
        #errorRatioSa = approxPrecSa/maxErrorSa
45 61 storres
        #print "Error ratio: ", errorRatioSa
46 81 storres
47 81 storres
        if shrinkFactorSa > intervalShrinkConstFactorSa:
48 81 storres
            actualShrinkFactorSa = intervalShrinkConstFactorSa
49 81 storres
            #print "Fixed"
50 61 storres
        else:
51 81 storres
            actualShrinkFactorSa = shrinkFactorSa
52 81 storres
            #print "Computed",shrinkFactorSa,maxErrorSa
53 81 storres
            #print shrinkFactorSa, maxErrorSa
54 81 storres
        currentUpperBoundSa = currentLowerBoundSa + \
55 61 storres
                                  (currentUpperBoundSa - currentLowerBoundSa) * \
56 81 storres
                                   actualShrinkFactorSa
57 71 storres
        #print "Current upper bound:", currentUpperBoundSa
58 61 storres
        sollya_lib_clear_obj(currentRangeSo)
59 61 storres
        sollya_lib_clear_obj(polySo)
60 86 storres
        if currentUpperBoundSa <= currentLowerBoundSa:
61 86 storres
            sollya_lib_clear_obj(absoluteErrorTypeSo)
62 86 storres
            print "Can't find an interval."
63 86 storres
            print "Use either or both a higher polynomial degree or a higher",
64 86 storres
            print "internal precision."
65 86 storres
            print "Aborting!"
66 86 storres
            return (None, None, None, None)
67 61 storres
        currentRangeSo = pobyso_bounds_to_range_sa_so(currentLowerBoundSa,
68 61 storres
                                                      currentUpperBoundSa)
69 86 storres
        # print "New interval:",
70 86 storres
        # pobyso_autoprint(currentRangeSo)
71 61 storres
        (polySo, intervalCenterSo, maxErrorSo) = \
72 61 storres
            pobyso_taylor_expansion_no_change_var_so_so(functionSo, degreeSo,
73 61 storres
                                                        currentRangeSo,
74 61 storres
                                                        absoluteErrorTypeSo)
75 61 storres
        #maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo, RRR)
76 85 storres
        #print "Max errorSo:",
77 85 storres
        #pobyso_autoprint(maxErrorSo)
78 61 storres
        maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
79 85 storres
        #print "Max errorSa:", maxErrorSa
80 85 storres
        #print "Sollya prec:",
81 85 storres
        #pobyso_autoprint(sollya_lib_get_prec(None))
82 61 storres
    sollya_lib_clear_obj(absoluteErrorTypeSo)
83 61 storres
    return((polySo, currentRangeSo, intervalCenterSo, maxErrorSo))
84 81 storres
# End slz_compute_polynomial_and_interval
85 61 storres
86 72 storres
def slz_compute_scaled_function(functionSa, \
87 72 storres
                                      lowerBoundSa, \
88 72 storres
                                      upperBoundSa, \
89 72 storres
                                      floatingPointPrecSa):
90 72 storres
    """
91 72 storres
    From a function, compute the scaled function whose domain
92 72 storres
    is included in [1, 2) and whose image is also included in [1,2).
93 72 storres
    Return a tuple:
94 72 storres
    [0]: the scaled function
95 72 storres
    [1]: the scaled domain lower bound
96 72 storres
    [2]: the scaled domain upper bound
97 72 storres
    [3]: the scaled image lower bound
98 72 storres
    [4]: the scaled image upper bound
99 72 storres
    """
100 80 storres
    x = functionSa.variables()[0]
101 80 storres
    # Reassert f as a function (an not a mere expression).
102 80 storres
103 72 storres
    # Scalling the domain -> [1,2[.
104 72 storres
    boundsIntervalRifSa = RealIntervalField(floatingPointPrecSa)
105 72 storres
    domainBoundsIntervalSa = boundsIntervalRifSa(lowerBoundSa, upperBoundSa)
106 72 storres
    (domainScalingExpressionSa, invDomainScalingExpressionSa) = \
107 80 storres
        slz_interval_scaling_expression(domainBoundsIntervalSa, x)
108 72 storres
    print "domainScalingExpression for argument :", domainScalingExpressionSa
109 72 storres
    print "f: ", f
110 72 storres
    ff = f.subs({x : domainScalingExpressionSa})
111 72 storres
    #ff = f.subs_expr(x==domainScalingExpressionSa)
112 80 storres
    domainScalingFunction(x) = invDomainScalingExpressionSa
113 80 storres
    scaledLowerBoundSa = domainScalingFunction(lowerBoundSa).n()
114 80 storres
    scaledUpperBoundSa = domainScalingFunction(upperBoundSa).n()
115 72 storres
    print 'ff:', ff, "- Domain:", scaledLowerBoundSa, scaledUpperBoundSa
116 72 storres
    #
117 72 storres
    # Scalling the image -> [1,2[.
118 72 storres
    flbSa = f(lowerBoundSa).n()
119 72 storres
    fubSa = f(upperBoundSa).n()
120 72 storres
    if flbSa <= fubSa: # Increasing
121 72 storres
        imageBinadeBottomSa = floor(flbSa.log2())
122 72 storres
    else: # Decreasing
123 72 storres
        imageBinadeBottomSa = floor(fubSa.log2())
124 72 storres
    print 'ff:', ff, '- Image:', flbSa, fubSa, imageBinadeBottomSa
125 72 storres
    imageBoundsIntervalSa = boundsIntervalRifSa(flbSa, fubSa)
126 72 storres
    (imageScalingExpressionSa, invImageScalingExpressionSa) = \
127 80 storres
        slz_interval_scaling_expression(imageBoundsIntervalSa, x)
128 72 storres
    iis = invImageScalingExpressionSa.function(x)
129 72 storres
    fff = iis.subs({x:ff})
130 72 storres
    print "fff:", fff,
131 72 storres
    print " - Image:", fff(scaledLowerBoundSa), fff(scaledUpperBoundSa)
132 72 storres
    return([fff, scaledLowerBoundSa, scaledUpperBoundSa, \
133 72 storres
            fff(scaledLowerBoundSa), fff(scaledUpperBoundSa)])
134 72 storres
135 79 storres
def slz_float_poly_of_float_to_rat_poly_of_rat(polyOfFloat):
136 79 storres
    # Create a polynomial over the rationals.
137 79 storres
    polynomialRing = QQ[str(polyOfFloat.variables()[0])]
138 79 storres
    return(polynomialRing(polyOfFloat))
139 86 storres
# End slz_float_poly_of_float_to_rat_poly_of_rat.
140 81 storres
141 80 storres
def slz_get_intervals_and_polynomials(functionSa, degreeSa,
142 63 storres
                                      lowerBoundSa,
143 60 storres
                                      upperBoundSa, floatingPointPrecSa,
144 64 storres
                                      internalSollyaPrecSa, approxPrecSa):
145 60 storres
    """
146 60 storres
    Under the assumption that:
147 60 storres
    - functionSa is monotonic on the [lowerBoundSa, upperBoundSa] interval;
148 60 storres
    - lowerBound and upperBound belong to the same binade.
149 60 storres
    from a:
150 60 storres
    - function;
151 60 storres
    - a degree
152 60 storres
    - a pair of bounds;
153 60 storres
    - the floating-point precision we work on;
154 60 storres
    - the internal Sollya precision;
155 64 storres
    - the requested approximation error
156 61 storres
    The initial interval is, possibly, splitted into smaller intervals.
157 61 storres
    It return a list of tuples, each made of:
158 72 storres
    - a first polynomial (without the changed variable f(x) = p(x-x0));
159 79 storres
    - a second polynomial (with a changed variable f(x) = q(x))
160 61 storres
    - the approximation interval;
161 72 storres
    - the center, x0, of the interval;
162 61 storres
    - the corresponding approximation error.
163 60 storres
    """
164 85 storres
    currentSollyaPrecSo = pobyso_get_prec_so()
165 85 storres
    currentSollyaPrecSa = pobyso_constant_from_int_so_sa(currentSollyaPrecSo)
166 85 storres
    if internalSollyaPrecSa > currentSollyaPrecSa:
167 85 storres
        pobyso_set_prec_sa_so(internalSollyaPrecSa)
168 80 storres
    x = functionSa.variables()[0] # Actual variable name can be anything.
169 80 storres
    (fff, scaledLowerBoundSa, scaledUpperBoundSa, \
170 80 storres
            scaledLowerBoundImageSa, scaledUpperBoundImageSa) = \
171 80 storres
                slz_compute_scaled_function(functionSa, \
172 80 storres
                                            lowerBoundSa, \
173 80 storres
                                            upperBoundSa, \
174 80 storres
                                            floatingPointPrecSa)
175 60 storres
    #
176 60 storres
    resultArray = []
177 60 storres
    #
178 60 storres
    print "Approximation precision: ", RR(approxPrecSa)
179 61 storres
    # Prepare the arguments for the Taylor expansion computation with Sollya.
180 62 storres
    functionSo = pobyso_parse_string_sa_so(fff._assume_str())
181 60 storres
    degreeSo = pobyso_constant_from_int_sa_so(degreeSa)
182 61 storres
    scaledBoundsSo = pobyso_bounds_to_range_sa_so(scaledLowerBoundSa,
183 61 storres
                                                  scaledUpperBoundSa)
184 61 storres
    # Compute the first Taylor expansion.
185 60 storres
    (polySo, boundsSo, intervalCenterSo, maxErrorSo) = \
186 60 storres
        slz_compute_polynomial_and_interval(functionSo, degreeSo,
187 60 storres
                                        scaledLowerBoundSa, scaledUpperBoundSa,
188 60 storres
                                        approxPrecSa, internalSollyaPrecSa)
189 86 storres
    if polySo is None:
190 86 storres
        print "Aborting"
191 86 storres
        return None
192 64 storres
    # Change variable stuff
193 62 storres
    changeVarExpressionSo = sollya_lib_build_function_sub(
194 62 storres
                              sollya_lib_build_function_free_variable(),
195 62 storres
                              sollya_lib_copy_obj(intervalCenterSo))
196 62 storres
    polyVarChangedSo = sollya_lib_evaluate(polySo, changeVarExpressionSo)
197 64 storres
    resultArray.append((polySo, polyVarChangedSo, boundsSo, intervalCenterSo,\
198 64 storres
                         maxErrorSo))
199 60 storres
    realIntervalField = RealIntervalField(max(lowerBoundSa.parent().precision(),
200 60 storres
                                              upperBoundSa.parent().precision()))
201 61 storres
    boundsSa = pobyso_range_to_interval_so_sa(boundsSo, realIntervalField)
202 81 storres
    # Compute the next upper bound.
203 81 storres
    # If the error of approximation is more than half of the target,
204 81 storres
    # use the same interval.
205 81 storres
    # If it is less, increase it a bit.
206 81 storres
    errorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
207 81 storres
    currentErrorRatio = approxPrecSa / errorSa
208 81 storres
    currentScaledUpperBoundSa = boundsSa.endpoints()[1]
209 81 storres
    if currentErrorRatio  < 2 :
210 81 storres
        currentScaledUpperBoundSa += \
211 81 storres
            (boundsSa.endpoints()[1] - boundsSa.endpoints()[0])
212 81 storres
    else:
213 81 storres
        currentScaledUpperBoundSa += \
214 81 storres
            (boundsSa.endpoints()[1] - boundsSa.endpoints()[0]) \
215 81 storres
                         * currentErrorRatio.log2() * 2
216 81 storres
    if currentScaledUpperBoundSa > scaledUpperBoundSa:
217 81 storres
        currentScaledUpperBoundSa = scaledUpperBoundSa
218 61 storres
    # Compute the other expansions.
219 60 storres
    while boundsSa.endpoints()[1] < scaledUpperBoundSa:
220 60 storres
        currentScaledLowerBoundSa = boundsSa.endpoints()[1]
221 60 storres
        (polySo, boundsSo, intervalCenterSo, maxErrorSo) = \
222 60 storres
            slz_compute_polynomial_and_interval(functionSo, degreeSo,
223 60 storres
                                            currentScaledLowerBoundSa,
224 81 storres
                                            currentScaledUpperBoundSa,
225 81 storres
                                            approxPrecSa,
226 60 storres
                                            internalSollyaPrecSa)
227 64 storres
        # Change variable stuff
228 64 storres
        changeVarExpressionSo = sollya_lib_build_function_sub(
229 64 storres
                                  sollya_lib_build_function_free_variable(),
230 64 storres
                                  sollya_lib_copy_obj(intervalCenterSo))
231 64 storres
        polyVarChangedSo = sollya_lib_evaluate(polySo, changeVarExpressionSo)
232 64 storres
        resultArray.append((polySo, polyVarChangedSo, boundsSo, \
233 64 storres
                            intervalCenterSo, maxErrorSo))
234 61 storres
        boundsSa = pobyso_range_to_interval_so_sa(boundsSo, realIntervalField)
235 81 storres
        # Compute the next upper bound.
236 81 storres
        # If the error of approximation is more than half of the target,
237 81 storres
        # use the same interval.
238 81 storres
        # If it is less, increase it a bit.
239 81 storres
        errorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
240 81 storres
        currentErrorRatio = approxPrecSa / errorSa
241 81 storres
        if currentErrorRatio  < RR('1.5') :
242 81 storres
            currentScaledUpperBoundSa = \
243 81 storres
                            boundsSa.endpoints()[1] + \
244 81 storres
                            (boundsSa.endpoints()[1] - boundsSa.endpoints()[0])
245 81 storres
        elif currentErrorRatio < 2:
246 81 storres
            currentScaledUpperBoundSa = \
247 81 storres
                            boundsSa.endpoints()[1] + \
248 81 storres
                            (boundsSa.endpoints()[1] - boundsSa.endpoints()[0]) \
249 81 storres
                             * currentErrorRatio.log2()
250 81 storres
        else:
251 81 storres
            currentScaledUpperBoundSa = \
252 81 storres
                            boundsSa.endpoints()[1] + \
253 81 storres
                            (boundsSa.endpoints()[1] - boundsSa.endpoints()[0]) \
254 81 storres
                             * currentErrorRatio.log2() * 2
255 85 storres
        # Test for insufficient precision.
256 85 storres
        if currentScaledUpperBoundSa == scaledLowerBoundSa:
257 85 storres
            print "Can't shrink the interval anymore!"
258 85 storres
            print "You should consider increasing the Sollya internal precision"
259 85 storres
            print "or the polynomial degree."
260 85 storres
            print "Giving up!"
261 85 storres
            sollya_lib_clear_obj(functionSo)
262 85 storres
            sollya_lib_clear_obj(degreeSo)
263 85 storres
            sollya_lib_clear_obj(scaledBoundsSo)
264 85 storres
            return None
265 81 storres
        if currentScaledUpperBoundSa > scaledUpperBoundSa:
266 81 storres
            currentScaledUpperBoundSa = scaledUpperBoundSa
267 60 storres
    sollya_lib_clear_obj(functionSo)
268 60 storres
    sollya_lib_clear_obj(degreeSo)
269 60 storres
    sollya_lib_clear_obj(scaledBoundsSo)
270 85 storres
    if internalSollyaPrecSa > currentSollyaPrecSa:
271 85 storres
        pobyso_set_prec_so_so(currentSollyaPrecSo)
272 60 storres
    return(resultArray)
273 81 storres
# End slz_get_intervals_and_polynomials
274 60 storres
275 81 storres
276 80 storres
def slz_interval_scaling_expression(boundsInterval, expVar):
277 61 storres
    """
278 61 storres
    Compute the scaling expression to map an interval that span only
279 62 storres
    a binade to [1, 2) and the inverse expression as well.
280 62 storres
    Not very sure that the transformation makes sense for negative numbers.
281 61 storres
    """
282 62 storres
    # The scaling offset is only used for negative numbers.
283 61 storres
    if abs(boundsInterval.endpoints()[0]) < 1:
284 61 storres
        if boundsInterval.endpoints()[0] >= 0:
285 62 storres
            scalingCoeff = 2^floor(boundsInterval.endpoints()[0].log2())
286 62 storres
            invScalingCoeff = 1/scalingCoeff
287 80 storres
            return((scalingCoeff * expVar,
288 80 storres
                    invScalingCoeff * expVar))
289 60 storres
        else:
290 62 storres
            scalingCoeff = \
291 62 storres
                2^(floor((-boundsInterval.endpoints()[0]).log2()) - 1)
292 62 storres
            scalingOffset = -3 * scalingCoeff
293 80 storres
            return((scalingCoeff * expVar + scalingOffset,
294 80 storres
                    1/scalingCoeff * expVar + 3))
295 61 storres
    else:
296 61 storres
        if boundsInterval.endpoints()[0] >= 0:
297 62 storres
            scalingCoeff = 2^floor(boundsInterval.endpoints()[0].log2())
298 61 storres
            scalingOffset = 0
299 80 storres
            return((scalingCoeff * expVar,
300 80 storres
                    1/scalingCoeff * expVar))
301 61 storres
        else:
302 62 storres
            scalingCoeff = \
303 62 storres
                2^(floor((-boundsInterval.endpoints()[1]).log2()))
304 62 storres
            scalingOffset =  -3 * scalingCoeff
305 62 storres
            #scalingOffset = 0
306 80 storres
            return((scalingCoeff * expVar + scalingOffset,
307 80 storres
                    1/scalingCoeff * expVar + 3))
308 61 storres
309 61 storres
310 83 storres
def slz_interval_and_polynomial_to_sage(polyRangeCenterErrorSo):
311 72 storres
    """
312 72 storres
    Compute the Sage version of the Taylor polynomial and it's
313 72 storres
    companion data (interval, center...)
314 72 storres
    The input parameter is a five elements tuple:
315 79 storres
    - [0]: the polyomial (without variable change), as polynomial over a
316 79 storres
           real ring;
317 79 storres
    - [1]: the polyomial (with variable change done in Sollya), as polynomial
318 79 storres
           over a real ring;
319 72 storres
    - [2]: the interval (as Sollya range);
320 72 storres
    - [3]: the interval center;
321 72 storres
    - [4]: the approximation error.
322 72 storres
323 72 storres
    The function return a 5 elements tuple: formed with all the
324 72 storres
    input elements converted into their Sollya counterpart.
325 72 storres
    """
326 60 storres
    polynomialSa = pobyso_get_poly_so_sa(polyRangeCenterErrorSo[0])
327 64 storres
    polynomialChangedVarSa = pobyso_get_poly_so_sa(polyRangeCenterErrorSo[1])
328 60 storres
    intervalSa = \
329 64 storres
            pobyso_get_interval_from_range_so_sa(polyRangeCenterErrorSo[2])
330 60 storres
    centerSa = \
331 64 storres
            pobyso_get_constant_as_rn_with_rf_so_sa(polyRangeCenterErrorSo[3])
332 60 storres
    errorSa = \
333 64 storres
            pobyso_get_constant_as_rn_with_rf_so_sa(polyRangeCenterErrorSo[4])
334 64 storres
    return((polynomialSa, polynomialChangedVarSa, intervalSa, centerSa, errorSa))
335 83 storres
    # End slz_interval_and_polynomial_to_sage
336 62 storres
337 80 storres
def slz_rat_poly_of_int_to_poly_for_coppersmith(ratPolyOfInt,
338 80 storres
                                                precision,
339 80 storres
                                                targetHardnessToRound,
340 80 storres
                                                variable1,
341 80 storres
                                                variable2):
342 80 storres
    """
343 90 storres
    Creates a new multivariate polynomial with integer coefficients for use
344 90 storres
     with the Coppersmith method.
345 80 storres
    A the same time it computes :
346 80 storres
    - 2^K (N);
347 90 storres
    - 2^k (bound on the second variable)
348 80 storres
    - lcm
349 90 storres
350 90 storres
    :param ratPolyOfInt: a polynomial with rational coefficients and integer
351 90 storres
                         variables.
352 90 storres
    :param precision: the precision of the floating-point coefficients.
353 90 storres
    :param targetHardnessToRound: the hardness to round we want to check.
354 90 storres
    :param variable1: the first variable of the polynomial (an expression).
355 90 storres
    :param variable2: the second variable of the polynomial (an expression).
356 90 storres
357 90 storres
    :returns: a 4 elements tuple:
358 90 storres
                - the polynomial;
359 91 storres
                - the modulus (N);
360 91 storres
                - the t bound;
361 90 storres
                - the lcm used to compute the integral coefficients and the
362 90 storres
                  module.
363 80 storres
    """
364 80 storres
    # Create a new integer polynomial ring.
365 80 storres
    IP = PolynomialRing(ZZ, name=str(variable1) + "," + str(variable2))
366 80 storres
    # Coefficients are issued in the increasing power order.
367 80 storres
    ratPolyCoefficients = ratPolyOfInt.coefficients()
368 91 storres
    # Print the reversed list for debugging.
369 94 storres
    print "Rational polynomial coefficients:", ratPolyCoefficients[::-1]
370 94 storres
    # Build the list of number we compute the lcm of.
371 80 storres
    coefficientDenominators = sro_denominators(ratPolyCoefficients)
372 80 storres
    coefficientDenominators.append(2^precision)
373 80 storres
    coefficientDenominators.append(2^(targetHardnessToRound + 1))
374 87 storres
    leastCommonMultiple = lcm(coefficientDenominators)
375 80 storres
    # Compute the expression corresponding to the new polynomial
376 80 storres
    coefficientNumerators =  sro_numerators(ratPolyCoefficients)
377 91 storres
    #print coefficientNumerators
378 80 storres
    polynomialExpression = 0
379 80 storres
    power = 0
380 80 storres
    # Iterate over two lists at the same time, stop when the shorter is
381 80 storres
    # exhausted.
382 80 storres
    for numerator, denominator in \
383 94 storres
                        zip(coefficientNumerators, coefficientDenominators):
384 80 storres
        multiplicator = leastCommonMultiple / denominator
385 80 storres
        newCoefficient = numerator * multiplicator
386 80 storres
        polynomialExpression += newCoefficient * variable1^power
387 80 storres
        power +=1
388 80 storres
    polynomialExpression += - variable2
389 80 storres
    return (IP(polynomialExpression),
390 80 storres
            leastCommonMultiple / 2^precision, # 2^K or N.
391 91 storres
            leastCommonMultiple / 2^(targetHardnessToRound + 1), # tBound
392 91 storres
            leastCommonMultiple) # If we want to make test computations.
393 80 storres
394 80 storres
# End slz_ratPoly_of_int_to_poly_for_coppersmith
395 79 storres
396 79 storres
def slz_rat_poly_of_rat_to_rat_poly_of_int(ratPolyOfRat,
397 79 storres
                                          precision):
398 79 storres
    """
399 79 storres
    Makes a variable substitution into the input polynomial so that the output
400 79 storres
    polynomial can take integer arguments.
401 79 storres
    All variables of the input polynomial "have precision p". That is to say
402 79 storres
    that they are rationals with denominator == 2^precision: x = y/2^precision
403 79 storres
    We "incorporate" these denominators into the coefficients with,
404 79 storres
    respectively, the "right" power.
405 79 storres
    """
406 79 storres
    polynomialField = ratPolyOfRat.parent()
407 91 storres
    polynomialVariable = ratPolyOfRat.variables()[0]
408 91 storres
    #print "The polynomial field is:", polynomialField
409 79 storres
    return \
410 91 storres
        polynomialField(ratPolyOfRat.subs({polynomialVariable : \
411 79 storres
                                   polynomialVariable/2^(precision-1)}))
412 79 storres
413 79 storres
    # Return a tuple:
414 79 storres
    # - the bivariate integer polynomial in (i,j);
415 79 storres
    # - 2^K
416 79 storres
# End slz_rat_poly_of_rat_to_rat_poly_of_int
417 79 storres
418 87 storres
print "\t...sageSLZ loaded"