Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (23,25 ko)

1 90 storres
"""
2 98 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 101 storres
        #print "++Approximation error:", maxErrorSa
40 61 storres
        sollya_lib_clear_obj(maxErrorSo)
41 81 storres
        sollya_lib_clear_obj(polySo)
42 81 storres
        sollya_lib_clear_obj(intervalCenterSo)
43 101 storres
        shrinkFactorSa = RRR('5')/(maxErrorSa/approxPrecSa).log2().abs()
44 81 storres
        #shrinkFactorSa = 1.5/(maxErrorSa/approxPrecSa)
45 81 storres
        #errorRatioSa = approxPrecSa/maxErrorSa
46 61 storres
        #print "Error ratio: ", errorRatioSa
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 101 storres
        #print "Shrink factor", actualShrinkFactorSa
55 81 storres
        currentUpperBoundSa = currentLowerBoundSa + \
56 61 storres
                                  (currentUpperBoundSa - currentLowerBoundSa) * \
57 81 storres
                                   actualShrinkFactorSa
58 71 storres
        #print "Current upper bound:", currentUpperBoundSa
59 61 storres
        sollya_lib_clear_obj(currentRangeSo)
60 61 storres
        sollya_lib_clear_obj(polySo)
61 101 storres
        if currentUpperBoundSa <= currentLowerBoundSa or \
62 101 storres
              currentUpperBoundSa == currentLowerBoundSa.nextabove():
63 86 storres
            sollya_lib_clear_obj(absoluteErrorTypeSo)
64 86 storres
            print "Can't find an interval."
65 86 storres
            print "Use either or both a higher polynomial degree or a higher",
66 86 storres
            print "internal precision."
67 86 storres
            print "Aborting!"
68 86 storres
            return (None, None, None, None)
69 61 storres
        currentRangeSo = pobyso_bounds_to_range_sa_so(currentLowerBoundSa,
70 61 storres
                                                      currentUpperBoundSa)
71 86 storres
        # print "New interval:",
72 86 storres
        # pobyso_autoprint(currentRangeSo)
73 61 storres
        (polySo, intervalCenterSo, maxErrorSo) = \
74 61 storres
            pobyso_taylor_expansion_no_change_var_so_so(functionSo, degreeSo,
75 61 storres
                                                        currentRangeSo,
76 61 storres
                                                        absoluteErrorTypeSo)
77 61 storres
        #maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo, RRR)
78 85 storres
        #print "Max errorSo:",
79 85 storres
        #pobyso_autoprint(maxErrorSo)
80 61 storres
        maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
81 85 storres
        #print "Max errorSa:", maxErrorSa
82 85 storres
        #print "Sollya prec:",
83 85 storres
        #pobyso_autoprint(sollya_lib_get_prec(None))
84 61 storres
    sollya_lib_clear_obj(absoluteErrorTypeSo)
85 61 storres
    return((polySo, currentRangeSo, intervalCenterSo, maxErrorSo))
86 81 storres
# End slz_compute_polynomial_and_interval
87 61 storres
88 98 storres
def slz_compute_reduced_polynomials(reducedMatrix,
89 98 storres
                                    knownMonomials,
90 106 storres
                                    var1,
91 98 storres
                                    var1Bound,
92 106 storres
                                    var2,
93 99 storres
                                    var2Bound):
94 98 storres
    """
95 98 storres
    From a reduced matrix, holding the coefficients, from a monomials list,
96 98 storres
    from the bounds of each variable, compute the corresponding polynomials
97 98 storres
    scaled back by dividing by the "right" powers of the variables bounds.
98 99 storres
99 99 storres
    The elements in knownMonomials must be of the "right" polynomial type.
100 103 storres
    They set the polynomial type of the output polynomials list.
101 98 storres
    """
102 99 storres
103 98 storres
    # TODO: check input arguments.
104 98 storres
    reducedPolynomials = []
105 106 storres
    #print "type var1:", type(var1), " - type var2:", type(var2)
106 98 storres
    for matrixRow in reducedMatrix.rows():
107 102 storres
        currentPolynomial = 0
108 98 storres
        for colIndex in xrange(0, len(knownMonomials)):
109 98 storres
            currentCoefficient = matrixRow[colIndex]
110 106 storres
            if currentCoefficient != 0:
111 106 storres
                #print "Current coefficient:", currentCoefficient
112 106 storres
                currentMonomial = knownMonomials[colIndex]
113 106 storres
                parentRing = currentMonomial.parent()
114 106 storres
                #print "Monomial as multivariate polynomial:", \
115 106 storres
                #currentMonomial, type(currentMonomial)
116 106 storres
                degreeInVar1 = currentMonomial.degree(parentRing(var1))
117 106 storres
                #print "Degree in var", var1, ":", degreeInVar1
118 106 storres
                degreeInVar2 = currentMonomial.degree(parentRing(var2))
119 106 storres
                #print "Degree in var", var2, ":", degreeInVar2
120 106 storres
                if degreeInVar1 > 0:
121 106 storres
                    currentCoefficient = \
122 106 storres
                        currentCoefficient / var1Bound^degreeInVar1
123 106 storres
                    #print "varBound1 in degree:", var1Bound^degreeInVar1
124 106 storres
                    #print "Current coefficient(1)", currentCoefficient
125 106 storres
                if degreeInVar2 > 0:
126 106 storres
                    currentCoefficient = \
127 106 storres
                        currentCoefficient / var2Bound^degreeInVar2
128 106 storres
                    #print "Current coefficient(2)", currentCoefficient
129 106 storres
                #print "Current reduced monomial:", (currentCoefficient * \
130 106 storres
                #                                    currentMonomial)
131 106 storres
                currentPolynomial += (currentCoefficient * currentMonomial)
132 106 storres
                #print "Current polynomial:", currentPolynomial
133 106 storres
            # End if
134 106 storres
        # End for colIndex.
135 99 storres
        #print "Type of the current polynomial:", type(currentPolynomial)
136 99 storres
        reducedPolynomials.append(currentPolynomial)
137 98 storres
    return reducedPolynomials
138 99 storres
# End slz_compute_reduced_polynomials.
139 98 storres
140 114 storres
def slz_compute_scaled_function(functionSa,
141 114 storres
                                lowerBoundSa,
142 114 storres
                                upperBoundSa,
143 114 storres
                                floatingPointPrecSa):
144 72 storres
    """
145 72 storres
    From a function, compute the scaled function whose domain
146 72 storres
    is included in [1, 2) and whose image is also included in [1,2).
147 72 storres
    Return a tuple:
148 72 storres
    [0]: the scaled function
149 72 storres
    [1]: the scaled domain lower bound
150 72 storres
    [2]: the scaled domain upper bound
151 72 storres
    [3]: the scaled image lower bound
152 72 storres
    [4]: the scaled image upper bound
153 72 storres
    """
154 80 storres
    x = functionSa.variables()[0]
155 80 storres
    # Reassert f as a function (an not a mere expression).
156 80 storres
157 72 storres
    # Scalling the domain -> [1,2[.
158 72 storres
    boundsIntervalRifSa = RealIntervalField(floatingPointPrecSa)
159 72 storres
    domainBoundsIntervalSa = boundsIntervalRifSa(lowerBoundSa, upperBoundSa)
160 72 storres
    (domainScalingExpressionSa, invDomainScalingExpressionSa) = \
161 80 storres
        slz_interval_scaling_expression(domainBoundsIntervalSa, x)
162 72 storres
    print "domainScalingExpression for argument :", domainScalingExpressionSa
163 72 storres
    print "f: ", f
164 72 storres
    ff = f.subs({x : domainScalingExpressionSa})
165 72 storres
    #ff = f.subs_expr(x==domainScalingExpressionSa)
166 80 storres
    domainScalingFunction(x) = invDomainScalingExpressionSa
167 80 storres
    scaledLowerBoundSa = domainScalingFunction(lowerBoundSa).n()
168 80 storres
    scaledUpperBoundSa = domainScalingFunction(upperBoundSa).n()
169 72 storres
    print 'ff:', ff, "- Domain:", scaledLowerBoundSa, scaledUpperBoundSa
170 72 storres
    #
171 72 storres
    # Scalling the image -> [1,2[.
172 72 storres
    flbSa = f(lowerBoundSa).n()
173 72 storres
    fubSa = f(upperBoundSa).n()
174 72 storres
    if flbSa <= fubSa: # Increasing
175 72 storres
        imageBinadeBottomSa = floor(flbSa.log2())
176 72 storres
    else: # Decreasing
177 72 storres
        imageBinadeBottomSa = floor(fubSa.log2())
178 72 storres
    print 'ff:', ff, '- Image:', flbSa, fubSa, imageBinadeBottomSa
179 72 storres
    imageBoundsIntervalSa = boundsIntervalRifSa(flbSa, fubSa)
180 72 storres
    (imageScalingExpressionSa, invImageScalingExpressionSa) = \
181 80 storres
        slz_interval_scaling_expression(imageBoundsIntervalSa, x)
182 72 storres
    iis = invImageScalingExpressionSa.function(x)
183 72 storres
    fff = iis.subs({x:ff})
184 72 storres
    print "fff:", fff,
185 72 storres
    print " - Image:", fff(scaledLowerBoundSa), fff(scaledUpperBoundSa)
186 72 storres
    return([fff, scaledLowerBoundSa, scaledUpperBoundSa, \
187 72 storres
            fff(scaledLowerBoundSa), fff(scaledUpperBoundSa)])
188 72 storres
189 79 storres
def slz_float_poly_of_float_to_rat_poly_of_rat(polyOfFloat):
190 79 storres
    # Create a polynomial over the rationals.
191 79 storres
    polynomialRing = QQ[str(polyOfFloat.variables()[0])]
192 79 storres
    return(polynomialRing(polyOfFloat))
193 86 storres
# End slz_float_poly_of_float_to_rat_poly_of_rat.
194 81 storres
195 80 storres
def slz_get_intervals_and_polynomials(functionSa, degreeSa,
196 63 storres
                                      lowerBoundSa,
197 60 storres
                                      upperBoundSa, floatingPointPrecSa,
198 64 storres
                                      internalSollyaPrecSa, approxPrecSa):
199 60 storres
    """
200 60 storres
    Under the assumption that:
201 60 storres
    - functionSa is monotonic on the [lowerBoundSa, upperBoundSa] interval;
202 60 storres
    - lowerBound and upperBound belong to the same binade.
203 60 storres
    from a:
204 60 storres
    - function;
205 60 storres
    - a degree
206 60 storres
    - a pair of bounds;
207 60 storres
    - the floating-point precision we work on;
208 60 storres
    - the internal Sollya precision;
209 64 storres
    - the requested approximation error
210 61 storres
    The initial interval is, possibly, splitted into smaller intervals.
211 61 storres
    It return a list of tuples, each made of:
212 72 storres
    - a first polynomial (without the changed variable f(x) = p(x-x0));
213 79 storres
    - a second polynomial (with a changed variable f(x) = q(x))
214 61 storres
    - the approximation interval;
215 72 storres
    - the center, x0, of the interval;
216 61 storres
    - the corresponding approximation error.
217 100 storres
    TODO: fix endless looping for some parameters sets.
218 60 storres
    """
219 101 storres
    # Set Sollya to the necessary internal precision.
220 85 storres
    currentSollyaPrecSo = pobyso_get_prec_so()
221 85 storres
    currentSollyaPrecSa = pobyso_constant_from_int_so_sa(currentSollyaPrecSo)
222 85 storres
    if internalSollyaPrecSa > currentSollyaPrecSa:
223 85 storres
        pobyso_set_prec_sa_so(internalSollyaPrecSa)
224 101 storres
    #
225 80 storres
    x = functionSa.variables()[0] # Actual variable name can be anything.
226 101 storres
    # Scaled function: [1=,2] -> [1,2].
227 80 storres
    (fff, scaledLowerBoundSa, scaledUpperBoundSa, \
228 80 storres
            scaledLowerBoundImageSa, scaledUpperBoundImageSa) = \
229 80 storres
                slz_compute_scaled_function(functionSa, \
230 80 storres
                                            lowerBoundSa, \
231 80 storres
                                            upperBoundSa, \
232 80 storres
                                            floatingPointPrecSa)
233 60 storres
    #
234 60 storres
    resultArray = []
235 60 storres
    #
236 60 storres
    print "Approximation precision: ", RR(approxPrecSa)
237 61 storres
    # Prepare the arguments for the Taylor expansion computation with Sollya.
238 62 storres
    functionSo = pobyso_parse_string_sa_so(fff._assume_str())
239 60 storres
    degreeSo = pobyso_constant_from_int_sa_so(degreeSa)
240 61 storres
    scaledBoundsSo = pobyso_bounds_to_range_sa_so(scaledLowerBoundSa,
241 61 storres
                                                  scaledUpperBoundSa)
242 61 storres
    # Compute the first Taylor expansion.
243 60 storres
    (polySo, boundsSo, intervalCenterSo, maxErrorSo) = \
244 60 storres
        slz_compute_polynomial_and_interval(functionSo, degreeSo,
245 60 storres
                                        scaledLowerBoundSa, scaledUpperBoundSa,
246 60 storres
                                        approxPrecSa, internalSollyaPrecSa)
247 86 storres
    if polySo is None:
248 101 storres
        print "slz_get_intervals_and_polynomials: Aborting and returning None!"
249 101 storres
        if internalSollyaPrecSa != currentSollyaPrecSa:
250 101 storres
            pobyso_set_prec_sa_so(currentSollyaPrecSa)
251 86 storres
        return None
252 60 storres
    realIntervalField = RealIntervalField(max(lowerBoundSa.parent().precision(),
253 60 storres
                                              upperBoundSa.parent().precision()))
254 61 storres
    boundsSa = pobyso_range_to_interval_so_sa(boundsSo, realIntervalField)
255 101 storres
    errorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
256 101 storres
    #print "First approximation error:", errorSa
257 101 storres
    # If the error and interval are OK a the first try, just return.
258 101 storres
    if boundsSa.endpoints()[1] >= scaledUpperBoundSa:
259 101 storres
        # Change variable stuff in Sollya x -> x0-x.
260 101 storres
        changeVarExpressionSo = sollya_lib_build_function_sub( \
261 101 storres
                              sollya_lib_build_function_free_variable(), \
262 101 storres
                              sollya_lib_copy_obj(intervalCenterSo))
263 101 storres
        polyVarChangedSo = sollya_lib_evaluate(polySo, changeVarExpressionSo)
264 101 storres
        resultArray.append((polySo, polyVarChangedSo, boundsSo, \
265 101 storres
                            intervalCenterSo, maxErrorSo))
266 101 storres
        if internalSollyaPrecSa != currentSollyaPrecSa:
267 101 storres
            pobyso_set_prec_sa_so(currentSollyaPrecSa)
268 101 storres
        sollya_lib_clear_obj(functionSo)
269 101 storres
        sollya_lib_clear_obj(degreeSo)
270 101 storres
        sollya_lib_clear_obj(scaledBoundsSo)
271 101 storres
        #print "Approximation error:", errorSa
272 101 storres
        return resultArray
273 81 storres
    # Compute the next upper bound.
274 101 storres
    # The following ratio is always >= 1
275 81 storres
    currentErrorRatio = approxPrecSa / errorSa
276 101 storres
    # Starting point for the next upper bound.
277 81 storres
    currentScaledUpperBoundSa = boundsSa.endpoints()[1]
278 101 storres
    boundsWidthSa = boundsSa.endpoints()[1] - boundsSa.endpoints()[0]
279 101 storres
    # Compute the increment.
280 101 storres
    if currentErrorRatio > RR('1000'): # ]1.5, infinity[
281 81 storres
        currentScaledUpperBoundSa += \
282 101 storres
                        currentErrorRatio * boundsWidthSa * 2
283 101 storres
    else:  # [1, 1.5]
284 81 storres
        currentScaledUpperBoundSa += \
285 101 storres
                        (RR('1.0') + currentErrorRatio.log() / 500) * boundsWidthSa
286 101 storres
    # Take into account the original interval upper bound.
287 81 storres
    if currentScaledUpperBoundSa > scaledUpperBoundSa:
288 81 storres
        currentScaledUpperBoundSa = scaledUpperBoundSa
289 61 storres
    # Compute the other expansions.
290 60 storres
    while boundsSa.endpoints()[1] < scaledUpperBoundSa:
291 60 storres
        currentScaledLowerBoundSa = boundsSa.endpoints()[1]
292 60 storres
        (polySo, boundsSo, intervalCenterSo, maxErrorSo) = \
293 60 storres
            slz_compute_polynomial_and_interval(functionSo, degreeSo,
294 60 storres
                                            currentScaledLowerBoundSa,
295 81 storres
                                            currentScaledUpperBoundSa,
296 81 storres
                                            approxPrecSa,
297 60 storres
                                            internalSollyaPrecSa)
298 101 storres
        errorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
299 101 storres
        if  errorSa < approxPrecSa:
300 101 storres
            # Change variable stuff
301 101 storres
            #print "Approximation error:", errorSa
302 101 storres
            changeVarExpressionSo = sollya_lib_build_function_sub(
303 101 storres
                                    sollya_lib_build_function_free_variable(),
304 101 storres
                                    sollya_lib_copy_obj(intervalCenterSo))
305 101 storres
            polyVarChangedSo = sollya_lib_evaluate(polySo, changeVarExpressionSo)
306 101 storres
            resultArray.append((polySo, polyVarChangedSo, boundsSo, \
307 101 storres
                                intervalCenterSo, maxErrorSo))
308 61 storres
        boundsSa = pobyso_range_to_interval_so_sa(boundsSo, realIntervalField)
309 81 storres
        # Compute the next upper bound.
310 101 storres
        # The following ratio is always >= 1
311 81 storres
        currentErrorRatio = approxPrecSa / errorSa
312 101 storres
        # Starting point for the next upper bound.
313 101 storres
        currentScaledUpperBoundSa = boundsSa.endpoints()[1]
314 101 storres
        boundsWidthSa = boundsSa.endpoints()[1] - boundsSa.endpoints()[0]
315 101 storres
        # Compute the increment.
316 101 storres
        if currentErrorRatio > RR('1000'): # ]1.5, infinity[
317 101 storres
            currentScaledUpperBoundSa += \
318 101 storres
                            currentErrorRatio * boundsWidthSa * 2
319 101 storres
        else:  # [1, 1.5]
320 101 storres
            currentScaledUpperBoundSa += \
321 101 storres
                            (RR('1.0') + currentErrorRatio.log()/500) * boundsWidthSa
322 101 storres
        #print "currentErrorRatio:", currentErrorRatio
323 101 storres
        #print "currentScaledUpperBoundSa", currentScaledUpperBoundSa
324 85 storres
        # Test for insufficient precision.
325 85 storres
        if currentScaledUpperBoundSa == scaledLowerBoundSa:
326 85 storres
            print "Can't shrink the interval anymore!"
327 85 storres
            print "You should consider increasing the Sollya internal precision"
328 85 storres
            print "or the polynomial degree."
329 85 storres
            print "Giving up!"
330 101 storres
            if internalSollyaPrecSa != currentSollyaPrecSa:
331 101 storres
                pobyso_set_prec_sa_so(currentSollyaPrecSa)
332 85 storres
            sollya_lib_clear_obj(functionSo)
333 85 storres
            sollya_lib_clear_obj(degreeSo)
334 85 storres
            sollya_lib_clear_obj(scaledBoundsSo)
335 85 storres
            return None
336 81 storres
        if currentScaledUpperBoundSa > scaledUpperBoundSa:
337 81 storres
            currentScaledUpperBoundSa = scaledUpperBoundSa
338 60 storres
    sollya_lib_clear_obj(functionSo)
339 60 storres
    sollya_lib_clear_obj(degreeSo)
340 60 storres
    sollya_lib_clear_obj(scaledBoundsSo)
341 85 storres
    if internalSollyaPrecSa > currentSollyaPrecSa:
342 85 storres
        pobyso_set_prec_so_so(currentSollyaPrecSo)
343 60 storres
    return(resultArray)
344 81 storres
# End slz_get_intervals_and_polynomials
345 60 storres
346 81 storres
347 80 storres
def slz_interval_scaling_expression(boundsInterval, expVar):
348 61 storres
    """
349 114 storres
    Compute the scaling expression to map an interval that span at most
350 114 storres
    a single binade to [1, 2) and the inverse expression as well.
351 62 storres
    Not very sure that the transformation makes sense for negative numbers.
352 61 storres
    """
353 62 storres
    # The scaling offset is only used for negative numbers.
354 61 storres
    if abs(boundsInterval.endpoints()[0]) < 1:
355 61 storres
        if boundsInterval.endpoints()[0] >= 0:
356 62 storres
            scalingCoeff = 2^floor(boundsInterval.endpoints()[0].log2())
357 62 storres
            invScalingCoeff = 1/scalingCoeff
358 80 storres
            return((scalingCoeff * expVar,
359 80 storres
                    invScalingCoeff * expVar))
360 60 storres
        else:
361 62 storres
            scalingCoeff = \
362 62 storres
                2^(floor((-boundsInterval.endpoints()[0]).log2()) - 1)
363 62 storres
            scalingOffset = -3 * scalingCoeff
364 80 storres
            return((scalingCoeff * expVar + scalingOffset,
365 80 storres
                    1/scalingCoeff * expVar + 3))
366 61 storres
    else:
367 61 storres
        if boundsInterval.endpoints()[0] >= 0:
368 62 storres
            scalingCoeff = 2^floor(boundsInterval.endpoints()[0].log2())
369 61 storres
            scalingOffset = 0
370 80 storres
            return((scalingCoeff * expVar,
371 80 storres
                    1/scalingCoeff * expVar))
372 61 storres
        else:
373 62 storres
            scalingCoeff = \
374 62 storres
                2^(floor((-boundsInterval.endpoints()[1]).log2()))
375 62 storres
            scalingOffset =  -3 * scalingCoeff
376 62 storres
            #scalingOffset = 0
377 80 storres
            return((scalingCoeff * expVar + scalingOffset,
378 80 storres
                    1/scalingCoeff * expVar + 3))
379 61 storres
380 61 storres
381 83 storres
def slz_interval_and_polynomial_to_sage(polyRangeCenterErrorSo):
382 72 storres
    """
383 72 storres
    Compute the Sage version of the Taylor polynomial and it's
384 72 storres
    companion data (interval, center...)
385 72 storres
    The input parameter is a five elements tuple:
386 79 storres
    - [0]: the polyomial (without variable change), as polynomial over a
387 79 storres
           real ring;
388 79 storres
    - [1]: the polyomial (with variable change done in Sollya), as polynomial
389 79 storres
           over a real ring;
390 72 storres
    - [2]: the interval (as Sollya range);
391 72 storres
    - [3]: the interval center;
392 72 storres
    - [4]: the approximation error.
393 72 storres
394 72 storres
    The function return a 5 elements tuple: formed with all the
395 72 storres
    input elements converted into their Sollya counterpart.
396 72 storres
    """
397 60 storres
    polynomialSa = pobyso_get_poly_so_sa(polyRangeCenterErrorSo[0])
398 64 storres
    polynomialChangedVarSa = pobyso_get_poly_so_sa(polyRangeCenterErrorSo[1])
399 60 storres
    intervalSa = \
400 64 storres
            pobyso_get_interval_from_range_so_sa(polyRangeCenterErrorSo[2])
401 60 storres
    centerSa = \
402 64 storres
            pobyso_get_constant_as_rn_with_rf_so_sa(polyRangeCenterErrorSo[3])
403 60 storres
    errorSa = \
404 64 storres
            pobyso_get_constant_as_rn_with_rf_so_sa(polyRangeCenterErrorSo[4])
405 64 storres
    return((polynomialSa, polynomialChangedVarSa, intervalSa, centerSa, errorSa))
406 83 storres
    # End slz_interval_and_polynomial_to_sage
407 62 storres
408 80 storres
def slz_rat_poly_of_int_to_poly_for_coppersmith(ratPolyOfInt,
409 80 storres
                                                precision,
410 80 storres
                                                targetHardnessToRound,
411 80 storres
                                                variable1,
412 80 storres
                                                variable2):
413 80 storres
    """
414 90 storres
    Creates a new multivariate polynomial with integer coefficients for use
415 90 storres
     with the Coppersmith method.
416 80 storres
    A the same time it computes :
417 80 storres
    - 2^K (N);
418 90 storres
    - 2^k (bound on the second variable)
419 80 storres
    - lcm
420 90 storres
421 90 storres
    :param ratPolyOfInt: a polynomial with rational coefficients and integer
422 90 storres
                         variables.
423 90 storres
    :param precision: the precision of the floating-point coefficients.
424 90 storres
    :param targetHardnessToRound: the hardness to round we want to check.
425 90 storres
    :param variable1: the first variable of the polynomial (an expression).
426 90 storres
    :param variable2: the second variable of the polynomial (an expression).
427 90 storres
428 90 storres
    :returns: a 4 elements tuple:
429 90 storres
                - the polynomial;
430 91 storres
                - the modulus (N);
431 91 storres
                - the t bound;
432 90 storres
                - the lcm used to compute the integral coefficients and the
433 90 storres
                  module.
434 80 storres
    """
435 80 storres
    # Create a new integer polynomial ring.
436 80 storres
    IP = PolynomialRing(ZZ, name=str(variable1) + "," + str(variable2))
437 80 storres
    # Coefficients are issued in the increasing power order.
438 80 storres
    ratPolyCoefficients = ratPolyOfInt.coefficients()
439 91 storres
    # Print the reversed list for debugging.
440 94 storres
    print "Rational polynomial coefficients:", ratPolyCoefficients[::-1]
441 94 storres
    # Build the list of number we compute the lcm of.
442 80 storres
    coefficientDenominators = sro_denominators(ratPolyCoefficients)
443 80 storres
    coefficientDenominators.append(2^precision)
444 80 storres
    coefficientDenominators.append(2^(targetHardnessToRound + 1))
445 87 storres
    leastCommonMultiple = lcm(coefficientDenominators)
446 80 storres
    # Compute the expression corresponding to the new polynomial
447 80 storres
    coefficientNumerators =  sro_numerators(ratPolyCoefficients)
448 91 storres
    #print coefficientNumerators
449 80 storres
    polynomialExpression = 0
450 80 storres
    power = 0
451 80 storres
    # Iterate over two lists at the same time, stop when the shorter is
452 80 storres
    # exhausted.
453 80 storres
    for numerator, denominator in \
454 94 storres
                        zip(coefficientNumerators, coefficientDenominators):
455 80 storres
        multiplicator = leastCommonMultiple / denominator
456 80 storres
        newCoefficient = numerator * multiplicator
457 80 storres
        polynomialExpression += newCoefficient * variable1^power
458 80 storres
        power +=1
459 80 storres
    polynomialExpression += - variable2
460 80 storres
    return (IP(polynomialExpression),
461 80 storres
            leastCommonMultiple / 2^precision, # 2^K or N.
462 91 storres
            leastCommonMultiple / 2^(targetHardnessToRound + 1), # tBound
463 91 storres
            leastCommonMultiple) # If we want to make test computations.
464 80 storres
465 80 storres
# End slz_ratPoly_of_int_to_poly_for_coppersmith
466 79 storres
467 79 storres
def slz_rat_poly_of_rat_to_rat_poly_of_int(ratPolyOfRat,
468 79 storres
                                          precision):
469 79 storres
    """
470 79 storres
    Makes a variable substitution into the input polynomial so that the output
471 79 storres
    polynomial can take integer arguments.
472 79 storres
    All variables of the input polynomial "have precision p". That is to say
473 103 storres
    that they are rationals with denominator == 2^(precision - 1):
474 103 storres
    x = y/2^(precision - 1).
475 79 storres
    We "incorporate" these denominators into the coefficients with,
476 79 storres
    respectively, the "right" power.
477 79 storres
    """
478 79 storres
    polynomialField = ratPolyOfRat.parent()
479 91 storres
    polynomialVariable = ratPolyOfRat.variables()[0]
480 91 storres
    #print "The polynomial field is:", polynomialField
481 79 storres
    return \
482 91 storres
        polynomialField(ratPolyOfRat.subs({polynomialVariable : \
483 79 storres
                                   polynomialVariable/2^(precision-1)}))
484 79 storres
485 79 storres
    # Return a tuple:
486 79 storres
    # - the bivariate integer polynomial in (i,j);
487 79 storres
    # - 2^K
488 79 storres
# End slz_rat_poly_of_rat_to_rat_poly_of_int
489 79 storres
490 87 storres
print "\t...sageSLZ loaded"