Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (18,58 ko)

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