Statistiques
| Branche: | Révision :

cvp / src / functions_for_cvp.sage @ 9cf1fb38

Historique | Voir | Annoter | Télécharger (32,95 ko)

1 9cf1fb38 Serge Torres
"""
2 9cf1fb38 Serge Torres
@file functions_for_cvp.sage
3 9cf1fb38 Serge Torres
@package functions_for_cvp
4 9645ea29 Serge Torres
Auxiliary functions used for CVP.
5 9cf1fb38 Serge Torres
6 9cf1fb38 Serge Torres
@author S.T.
7 9645ea29 Serge Torres
"""
8 9645ea29 Serge Torres
print "Functions for CVP loading..."
9 9645ea29 Serge Torres
#
10 04d64614 Serge Torres
def cvp_affine_from_chebyshev(lowerBound, upperBound):
11 04d64614 Serge Torres
    """
12 04d64614 Serge Torres
    Compute the affine parameters to map [-1, 1] to the interval given
13 04d64614 Serge Torres
    as argument.
14 9cf1fb38 Serge Torres
    @param: lowerBound (of the target interval)
15 9cf1fb38 Serge Torres
    @param: upperBound (of the target interval)
16 04d64614 Serge Torres
    @return the (scalingCoefficient, offset) tuple.
17 04d64614 Serge Torres
    """
18 04d64614 Serge Torres
    ## Check bounds consistency. Bounds must differ.
19 04d64614 Serge Torres
    if lowerBound >= upperBound:
20 04d64614 Serge Torres
        return None
21 04d64614 Serge Torres
    scalingCoefficient = (upperBound - lowerBound) / 2
22 04d64614 Serge Torres
    offset             = (lowerBound + upperBound) / 2
23 04d64614 Serge Torres
    return (scalingCoefficient, offset)
24 04d64614 Serge Torres
# End cvp_affine_from_chebyshev
25 04d64614 Serge Torres
#
26 04d64614 Serge Torres
def cvp_affine_to_chebyshev(lowerBound, upperBound):
27 04d64614 Serge Torres
    """
28 04d64614 Serge Torres
    Compute the affine parameters to map the interval given
29 04d64614 Serge Torres
    as argument to  [-1, 1].
30 04d64614 Serge Torres
    @param lowerBound (of the target interval)
31 04d64614 Serge Torres
    @param upperBound (of the target interval)
32 04d64614 Serge Torres
    @return the (scalingCoefficient, offset) tuple.
33 04d64614 Serge Torres
    """
34 04d64614 Serge Torres
    ## Check bounds consistency. Bounds must differ.
35 04d64614 Serge Torres
    if lowerBound >= upperBound:
36 04d64614 Serge Torres
        return None
37 04d64614 Serge Torres
    scalingCoefficient = 2 / (upperBound - lowerBound)
38 04d64614 Serge Torres
    ## If bounds are symmetrical with relation to 0, return 0 straight before
39 04d64614 Serge Torres
    #  attempting a division by 0.
40 04d64614 Serge Torres
    if lowerBound == -upperBound:
41 04d64614 Serge Torres
        offset         = 0
42 04d64614 Serge Torres
    else:
43 04d64614 Serge Torres
        offset         =  (lowerBound + upperBound) / (lowerBound - upperBound)
44 04d64614 Serge Torres
    return (scalingCoefficient, offset)
45 04d64614 Serge Torres
# End cvp_affine_to_chebyshev
46 04d64614 Serge Torres
#
47 9645ea29 Serge Torres
def cvp_babai(redBasis, redBasisGso, vect):
48 9645ea29 Serge Torres
    """
49 9645ea29 Serge Torres
    Closest plane vector implementation as per Babaï.
50 9645ea29 Serge Torres
    @param redBasis   : a lattice basis, preferably a reduced one; 
51 9645ea29 Serge Torres
    @param redBasisGSO: the GSO of the previous basis;
52 9645ea29 Serge Torres
    @param vector     : a vector, in coordinated in the ambient 
53 9645ea29 Serge Torres
                        space of the lattice
54 9645ea29 Serge Torres
    @return the closest vector to the input, in coordinates in the 
55 9645ea29 Serge Torres
                        ambient space of the lattice.
56 9645ea29 Serge Torres
    """
57 9645ea29 Serge Torres
    ## A deep copy is not necessary here.
58 9645ea29 Serge Torres
    curVect = copy(vect)
59 62861417 Serge Torres
    print "cvp_babai - Vector:", vect
60 9645ea29 Serge Torres
    ## From index of last row down to 0.
61 9645ea29 Serge Torres
    for vIndex in xrange(len(redBasis.rows())-1, -1, -1):
62 9645ea29 Serge Torres
        curRBGSO = redBasisGso.row(vIndex)
63 724064f1 Serge Torres
        curVect = curVect - \
64 724064f1 Serge Torres
                  (round((curVect * curRBGSO)  / (curRBGSO * curRBGSO)) * \
65 724064f1 Serge Torres
                   redBasis.row(vIndex)) 
66 9645ea29 Serge Torres
    return vect - curVect
67 62861417 Serge Torres
# End cvp_babai
68 9645ea29 Serge Torres
#
69 9645ea29 Serge Torres
def cvp_bkz_reduce(intBasis, blockSize):
70 9645ea29 Serge Torres
    """
71 9645ea29 Serge Torres
    Thin and simplistic wrapper the HKZ function of the FP_LLL module.
72 9645ea29 Serge Torres
    """
73 9645ea29 Serge Torres
    fplllIntBasis = FP_LLL(intBasis)
74 9645ea29 Serge Torres
    fplllIntBasis.BKZ(blockSize)
75 9645ea29 Serge Torres
    return fplllIntBasis._sage_()
76 9645ea29 Serge Torres
# End cvp_hkz_reduce.
77 9645ea29 Serge Torres
#
78 9cf1fb38 Serge Torres
def cvp_candidate_vectors(intVect, diffsList):
79 9cf1fb38 Serge Torres
    """
80 9cf1fb38 Serge Torres
    Computes a list of best approximation vectors based on the CVP
81 9cf1fb38 Serge Torres
    computed vector using the differences between this vector and the 
82 9cf1fb38 Serge Torres
    target function vector.
83 9cf1fb38 Serge Torres
    @param intVect the vector from which candidates are built
84 9cf1fb38 Serge Torres
    @param diffsList the list of the values that will be appended to the
85 9cf1fb38 Serge Torres
           initial vector to form the candidates
86 9cf1fb38 Serge Torres
    @return A matrix made of candidates rows or None if there is some invalid
87 9cf1fb38 Serge Torres
            argument.
88 9cf1fb38 Serge Torres
    @par How it works
89 9cf1fb38 Serge Torres
    The idea is to create all the possible vectors based on the computed CVP
90 9cf1fb38 Serge Torres
    vector and its differences to the target. Those are collected in 
91 9cf1fb38 Serge Torres
    diffsList.@n
92 9cf1fb38 Serge Torres
    From the vector we create all the possible combinations between the original
93 9cf1fb38 Serge Torres
    value and the differences in diffsList. Some of those can be equal to 0.
94 9cf1fb38 Serge Torres
    They are not taken into account. If nonZeroDiffsCount is the number of 
95 9cf1fb38 Serge Torres
    diffsList element different from 0, there are 2^nonZeroDiffsCount 
96 9cf1fb38 Serge Torres
    possible variants.@n
97 9cf1fb38 Serge Torres
    To compute those, we build a 2^nonZeroDiffsCount rows matrix. For the
98 9cf1fb38 Serge Torres
    first element in the vector corresponding to a non-zero in diffsList, we
99 9cf1fb38 Serge Torres
    switch values in the matrix at every row.@n
100 9cf1fb38 Serge Torres
    For the second such element (non-zero corresponding diffsList element), we
101 9cf1fb38 Serge Torres
    switch values in the matrix at every second row for a string of two similar 
102 9cf1fb38 Serge Torres
    values.@n
103 9cf1fb38 Serge Torres
    For the third such element, change happens at every fourth row, for a 
104 9cf1fb38 Serge Torres
    string of four similar values. And so on...
105 9cf1fb38 Serge Torres
    @par Example
106 9cf1fb38 Serge Torres
    @verbatim
107 9cf1fb38 Serge Torres
    vect        =  [10, 20, 30, 40, 50]
108 9cf1fb38 Serge Torres
    diffsList   =  [ 1,  0, -1,  0,  1]
109 9cf1fb38 Serge Torres
    vectCandMat = [[10, 20, 30, 40, 50],
110 9cf1fb38 Serge Torres
                   [11, 20, 30, 40, 50],
111 9cf1fb38 Serge Torres
                   [10, 20, 29, 40, 50],
112 9cf1fb38 Serge Torres
                   [11, 20, 29, 40, 50],
113 9cf1fb38 Serge Torres
                   [10, 20, 30, 40, 51],
114 9cf1fb38 Serge Torres
                   [11, 20, 30, 40, 51],
115 9cf1fb38 Serge Torres
                   [10, 20, 29, 40, 51],
116 9cf1fb38 Serge Torres
                   [11, 20, 29, 40, 51]]
117 9cf1fb38 Serge Torres
    @endverbatim
118 9cf1fb38 Serge Torres
"""
119 9cf1fb38 Serge Torres
    ## Arguments check.
120 9cf1fb38 Serge Torres
    vectLen = len(intVect)
121 9cf1fb38 Serge Torres
    if vectLen != len(diffsList):
122 9cf1fb38 Serge Torres
        return None
123 9cf1fb38 Serge Torres
    #
124 9cf1fb38 Serge Torres
    ## Compute the number of diffsList elements different from 0.
125 9cf1fb38 Serge Torres
    nonZeroDiffsCount = 0
126 9cf1fb38 Serge Torres
    for elem in diffsList:
127 9cf1fb38 Serge Torres
        if elem != 0:
128 9cf1fb38 Serge Torres
            nonZeroDiffsCount += 1
129 9cf1fb38 Serge Torres
    if nonZeroDiffsCount == 0:
130 9cf1fb38 Serge Torres
        return matrix(ZZ, 0, vectLen)
131 9cf1fb38 Serge Torres
    numRows = 2^nonZeroDiffsCount
132 9cf1fb38 Serge Torres
    vectMat = matrix(ZZ, numRows, vectLen)
133 9cf1fb38 Serge Torres
    for rowIndex in xrange(0,numRows):
134 9cf1fb38 Serge Torres
        effColIndex = 0
135 9cf1fb38 Serge Torres
        for colIndex in xrange(0,vectLen):
136 9cf1fb38 Serge Torres
            vectMat[rowIndex, colIndex] = intVect[colIndex]
137 9cf1fb38 Serge Torres
            if diffsList[colIndex] != 0:
138 9cf1fb38 Serge Torres
                if (rowIndex % 2^(effColIndex + 1)) >= 2^effColIndex:
139 9cf1fb38 Serge Torres
                    vectMat[rowIndex, colIndex] += diffsList[colIndex]
140 9cf1fb38 Serge Torres
                effColIndex += 1
141 9cf1fb38 Serge Torres
    return vectMat
142 9cf1fb38 Serge Torres
# End cvp_candidate_vectors
143 9cf1fb38 Serge Torres
#
144 04d64614 Serge Torres
def cvp_coefficients_bounds_projection(executablePath, arguments):
145 04d64614 Serge Torres
    """
146 04d64614 Serge Torres
    Compute the min and max of the coefficients with linear
147 04d64614 Serge Torres
    programming projection.
148 04d64614 Serge Torres
    @param executablePath: the path to the binary program;
149 04d64614 Serge Torres
    @param arguments: a list of arguments to be givent to the binary
150 04d64614 Serge Torres
    @return: the min and max coefficients value arrays (in this order).
151 04d64614 Serge Torres
    """
152 04d64614 Serge Torres
    from subprocess import check_output
153 04d64614 Serge Torres
    commandLine = [executablePath] + arguments
154 04d64614 Serge Torres
    ## Get rid of output on stderr.
155 04d64614 Serge Torres
    devNull = open("/dev/null", "rw")
156 04d64614 Serge Torres
    ## Run ther program.
157 04d64614 Serge Torres
    otp = check_output(commandLine, stderr=devNull)
158 04d64614 Serge Torres
    devNull.close()
159 04d64614 Serge Torres
    ## Recover the results
160 04d64614 Serge Torres
    bounds = sage_eval(otp)
161 04d64614 Serge Torres
    minCoeffsExpList = []
162 04d64614 Serge Torres
    maxCoeffsExpList = [] 
163 9b0c03e7 Serge Torres
    #print "bounds:", bounds
164 04d64614 Serge Torres
    for boundsPair in bounds:
165 04d64614 Serge Torres
        minCoeffsExpList.append(boundsPair[0])
166 04d64614 Serge Torres
        maxCoeffsExpList.append(boundsPair[1])
167 04d64614 Serge Torres
    print "minCoeffsExpList:", minCoeffsExpList
168 04d64614 Serge Torres
    print "maxCoeffsExpList:", maxCoeffsExpList
169 04d64614 Serge Torres
    return (minCoeffsExpList, maxCoeffsExpList)
170 04d64614 Serge Torres
# End cvp_coefficients_bounds_projection
171 04d64614 Serge Torres
172 04d64614 Serge Torres
def cvp_coefficients_bounds_projection_exps(executablePath, 
173 04d64614 Serge Torres
                                            arguments, 
174 04d64614 Serge Torres
                                            realField = None):
175 04d64614 Serge Torres
    """
176 04d64614 Serge Torres
    Compute the min and max exponents of the coefficients with linear
177 04d64614 Serge Torres
    programming projection.
178 04d64614 Serge Torres
    @param executablePath: the path to the binary program;
179 04d64614 Serge Torres
    @param arguments: a list of arguments to be givent to the binary
180 04d64614 Serge Torres
    @param realField: the realField to use for floating-point conversion.
181 04d64614 Serge Torres
    @return: the min and max exponents arrays (in this order).
182 04d64614 Serge Torres
    """
183 04d64614 Serge Torres
    ## If no realField is givne, fall back on RR.
184 04d64614 Serge Torres
    if realField is None:
185 04d64614 Serge Torres
        realField = RR
186 04d64614 Serge Torres
    (minCoeffsExpList, maxCoeffsExpList) = \
187 04d64614 Serge Torres
        cvp_coefficients_bounds_projection(executablePath,arguments)
188 04d64614 Serge Torres
    for index in xrange(0, len(minCoeffsExpList)):
189 04d64614 Serge Torres
        minCoeffsExpList[index] = \
190 9b0c03e7 Serge Torres
            realField(minCoeffsExpList[index]).abs().log2().floor()
191 04d64614 Serge Torres
        maxCoeffsExpList[index] = \
192 9b0c03e7 Serge Torres
            realField(maxCoeffsExpList[index]).abs().log2().floor()
193 04d64614 Serge Torres
    return (minCoeffsExpList, maxCoeffsExpList)
194 04d64614 Serge Torres
# End cvp_coefficients_bounds_projection_exps
195 04d64614 Serge Torres
196 04d64614 Serge Torres
def cvp_chebyshev_zeros_1k(numPoints, realField, contFracMaxErr = None):
197 04d64614 Serge Torres
    """
198 04d64614 Serge Torres
    Compute the Chebyshev zeros for some polynomial degree (numPoints, for the
199 04d64614 Serge Torres
    zeros) scaled to the [lowerBound, upperBound] interval.
200 04d64614 Serge Torres
    The list is returned as row floating-point numbers is contFracMaxErr is None.
201 04d64614 Serge Torres
    Otherwise elements are transformed into rational numbers. 
202 04d64614 Serge Torres
    """
203 04d64614 Serge Torres
    if numPoints < 1:
204 04d64614 Serge Torres
        return None
205 04d64614 Serge Torres
    if numPoints == 0:
206 04d64614 Serge Torres
        return [0]
207 04d64614 Serge Torres
    ## Check that realField has a "prec()" member.
208 04d64614 Serge Torres
    try:
209 04d64614 Serge Torres
        realField.prec()
210 04d64614 Serge Torres
    except:
211 04d64614 Serge Torres
        return None
212 04d64614 Serge Torres
    #
213 04d64614 Serge Torres
    zerosList = []
214 04d64614 Serge Torres
    ## formulas: cos (((2*i - 1) * pi) / (2*numPoints)) for i = 1,...,numPoints.
215 04d64614 Serge Torres
    #  If i is -1-shifted, as in the following loop, formula is 
216 04d64614 Serge Torres
    #  cos (((2*i + 1) * pi) / (2*numPoints)) for i = 0,...,numPoints-1.
217 04d64614 Serge Torres
    for index in xrange(0, numPoints):
218 04d64614 Serge Torres
        ## When number of points is odd (then, the Chebyshev degree is odd two), 
219 04d64614 Serge Torres
        #  the central point is 0. */
220 04d64614 Serge Torres
        if (numPoints % 2 == 1) and ((2 * index + 1) == numPoints):
221 04d64614 Serge Torres
            if contFracMaxErr is None:
222 04d64614 Serge Torres
                zerosList.append(realField(0))
223 04d64614 Serge Torres
            else:
224 04d64614 Serge Torres
                zerosList.append(0)
225 04d64614 Serge Torres
        else:
226 04d64614 Serge Torres
            currentCheby = \
227 04d64614 Serge Torres
                ((realField(2*index+1) * realField(pi)) / 
228 04d64614 Serge Torres
                 realField(2*numPoints)).cos()
229 04d64614 Serge Torres
            #print  "Current Cheby:", currentCheby
230 04d64614 Serge Torres
            ## Result is negated to have an increasing order list.
231 04d64614 Serge Torres
            if contFracMaxErr is None:
232 04d64614 Serge Torres
                zerosList.append(-currentCheby)
233 04d64614 Serge Torres
            else:
234 04d64614 Serge Torres
                zerosList.append(-currentCheby.nearby_rational(contFracMaxErr))
235 04d64614 Serge Torres
            #print "Relative error:", (currentCheby/zerosList[index])
236 04d64614 Serge Torres
    return zerosList
237 04d64614 Serge Torres
# End cvp_chebyshev_zeros_1k.
238 04d64614 Serge Torres
#
239 04d64614 Serge Torres
def cvp_chebyshev_zeros_for_interval(lowerBound, 
240 04d64614 Serge Torres
                                     upperBound, 
241 04d64614 Serge Torres
                                     numPoints,
242 04d64614 Serge Torres
                                     realField = None, 
243 04d64614 Serge Torres
                                     contFracMaxErr = None):
244 04d64614 Serge Torres
    """
245 04d64614 Serge Torres
    Compute the Chebyshev zeros for some polynomial degree (numPoints, for the
246 04d64614 Serge Torres
    zeros) scaled to the [lowerBound, upperBound] interval.
247 04d64614 Serge Torres
    If no contFracMaxErr argument is given, we return the list as "raw"
248 04d64614 Serge Torres
    floating-points. Otherwise, rational numbers are returned.
249 04d64614 Serge Torres
    """
250 04d64614 Serge Torres
    ## Arguments check.
251 04d64614 Serge Torres
    if lowerBound >= upperBound:
252 04d64614 Serge Torres
        return None
253 04d64614 Serge Torres
    if numPoints < 1:
254 04d64614 Serge Torres
        return None
255 04d64614 Serge Torres
    ## If no realField argument is given try to retrieve it from the 
256 04d64614 Serge Torres
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
257 04d64614 Serge Torres
    if realField is None:
258 04d64614 Serge Torres
        try:
259 04d64614 Serge Torres
            ### Force failure if parent does not have prec() member.
260 04d64614 Serge Torres
            lowerBound.parent().prec()
261 04d64614 Serge Torres
            ### If no exception is thrown, set realField.
262 04d64614 Serge Torres
            realField = lowerBound.parent()
263 04d64614 Serge Torres
        except:
264 04d64614 Serge Torres
            realField = RR
265 04d64614 Serge Torres
    #print "Real field:", realField
266 04d64614 Serge Torres
    ## We want "raw"floating-point nodes to only have one final rounding.
267 04d64614 Serge Torres
    chebyshevZerosList = \
268 04d64614 Serge Torres
        cvp_chebyshev_zeros_1k(numPoints, realField)
269 04d64614 Serge Torres
    scalingFactor, offset = cvp_affine_from_chebyshev(lowerBound, upperBound)
270 04d64614 Serge Torres
    for index in xrange(0, len(chebyshevZerosList)):
271 04d64614 Serge Torres
        chebyshevZerosList[index] = \
272 04d64614 Serge Torres
            chebyshevZerosList[index] * scalingFactor + offset
273 04d64614 Serge Torres
        if not contFracMaxErr is None:
274 04d64614 Serge Torres
            chebyshevZerosList[index] = \
275 04d64614 Serge Torres
                chebyshevZerosList[index].nearby_rational(contFracMaxErr)
276 04d64614 Serge Torres
    return chebyshevZerosList                                                             
277 04d64614 Serge Torres
# End cvp_chebyshev_zeros_for_interval.
278 04d64614 Serge Torres
#
279 62861417 Serge Torres
def cvp_common_scaling_exp(precision, 
280 62861417 Serge Torres
                           precisionFraction = None):
281 9645ea29 Serge Torres
    """
282 9645ea29 Serge Torres
    Compute the common scaling factor (a power of 2).
283 62861417 Serge Torres
    The exponent is a fraction of the precision;
284 62861417 Serge Torres
    A extra factor is computed for the vector,
285 62861417 Serge Torres
    exra factors are computed for the basis vectors, all in the corresponding
286 62861417 Serge Torres
    functions.
287 9645ea29 Serge Torres
    """
288 9645ea29 Serge Torres
    ## Set a default value for the precisionFraction to 1/2.
289 9645ea29 Serge Torres
    if precisionFraction is None:
290 62861417 Serge Torres
        precisionFraction = 3/4
291 62861417 Serge Torres
    """
292 9645ea29 Serge Torres
    minBasisVectsNorm = oo
293 9645ea29 Serge Torres
    currentNorm = 0
294 9645ea29 Serge Torres
    for vect in floatBasis.rows():
295 9645ea29 Serge Torres
        currentNorm = vect.norm()
296 9645ea29 Serge Torres
        print "Current norm:", currentNorm
297 9645ea29 Serge Torres
        if currentNorm < minBasisVectsNorm:
298 9645ea29 Serge Torres
            minBasisVectsNorm = currentNorm
299 9645ea29 Serge Torres
    currentNorm = funcVect.norm()
300 9645ea29 Serge Torres
    print "Current norm:", currentNorm
301 9645ea29 Serge Torres
    if currentNorm < minBasisVectsNorm:
302 9645ea29 Serge Torres
        minBasisVectsNorm = currentNorm
303 9645ea29 Serge Torres
    ## Check if a push is need because the smallest norm is below 0.    
304 9645ea29 Serge Torres
    powerForMinNorm = floor(log(minBasisVectsNorm)/log2)
305 9645ea29 Serge Torres
    print "Power for min norm :", powerForMinNorm
306 9645ea29 Serge Torres
    print "Power for precision:", ceil(precision*precisionFraction)
307 9645ea29 Serge Torres
    if powerForMinNorm < 0:
308 9645ea29 Serge Torres
        return 2^(ceil(precision*precisionFraction) - powerFromMinNorm)
309 9645ea29 Serge Torres
    else:
310 62861417 Serge Torres
    """
311 62861417 Serge Torres
    return ceil(precision * precisionFraction)
312 9645ea29 Serge Torres
# End cvp_common_scaling_factor.
313 9645ea29 Serge Torres
#
314 724064f1 Serge Torres
def cvp_evaluation_points_list(funct, 
315 724064f1 Serge Torres
                               maxDegree, 
316 724064f1 Serge Torres
                               lowerBound, 
317 724064f1 Serge Torres
                               upperBound, 
318 724064f1 Serge Torres
                               realField = None):
319 724064f1 Serge Torres
    """
320 724064f1 Serge Torres
    Compute a list of points for the vector creation.
321 724064f1 Serge Torres
    Strategy:
322 724064f1 Serge Torres
    - compute the zeros of the function-remez;
323 724064f1 Serge Torres
    - compute the zeros of the function-rounded_remez;
324 724064f1 Serge Torres
    - compute the Chebyshev points.
325 724064f1 Serge Torres
    Merge the whole thing.
326 724064f1 Serge Torres
    """
327 724064f1 Serge Torres
    
328 724064f1 Serge Torres
# End cvp_evaluation_points_list.
329 724064f1 Serge Torres
#
330 62861417 Serge Torres
def cvp_extra_basis_scaling_exps(precsList, minExponentsList):
331 9cf1fb38 Serge Torres
    """
332 9cf1fb38 Serge Torres
    Computes the exponents for the extra scaling down of the elements of the
333 9cf1fb38 Serge Torres
    basis.
334 9cf1fb38 Serge Torres
    This extra scaling down is necessary when there are elements of the 
335 9cf1fb38 Serge Torres
    basis that have negative exponents.
336 9cf1fb38 Serge Torres
    """
337 62861417 Serge Torres
    extraScalingExpsList = []
338 62861417 Serge Torres
    for minExp, prec in zip(minExponentsList, precsList):
339 62861417 Serge Torres
        if minExp - prec < 0:
340 62861417 Serge Torres
            extraScalingExpsList.append(minExp - prec)
341 62861417 Serge Torres
        else:
342 62861417 Serge Torres
            extraScalingExpsList.append(0)
343 62861417 Serge Torres
    return extraScalingExpsList
344 62861417 Serge Torres
# End cvp_extra_basis_scaling_exps.
345 62861417 Serge Torres
#
346 62861417 Serge Torres
def cvp_extra_function_scaling_exp(floatBasis,
347 62861417 Serge Torres
                                   floatFuncVect,
348 62861417 Serge Torres
                                   maxExponentsList):
349 9645ea29 Serge Torres
    """
350 62861417 Serge Torres
    Compute the extra scaling exponent for the function vector in ordre to 
351 62861417 Serge Torres
    guarantee that the maximum exponent can be reached for each element of the
352 62861417 Serge Torres
    basis.
353 9645ea29 Serge Torres
    """
354 62861417 Serge Torres
    ## Check arguments
355 9645ea29 Serge Torres
    if floatBasis.nrows() == 0 or \
356 9645ea29 Serge Torres
       floatBasis.ncols() == 0 or \
357 62861417 Serge Torres
       len(floatFuncVect)      == 0:
358 62861417 Serge Torres
        return 1
359 62861417 Serge Torres
    if len(maxExponentsList) != floatBasis.nrows():
360 62861417 Serge Torres
        return None
361 62861417 Serge Torres
    ## Compute the log of the norm of the function vector.
362 62861417 Serge Torres
    funcVectNormLog  = log(floatFuncVect.norm())
363 9645ea29 Serge Torres
    ## Compute the extra scaling factor for each vector of the basis.
364 62861417 Serge Torres
    #  for norms ratios an maxExponentsList. 
365 62861417 Serge Torres
    extraScalingExp = 0
366 62861417 Serge Torres
    for (row, maxExp) in zip(floatBasis.rows(),maxExponentsList):
367 62861417 Serge Torres
        rowNormLog     = log(row.norm())
368 62861417 Serge Torres
        normsRatioLog2 = floor((funcVectNormLog - rowNormLog) / log2) 
369 62861417 Serge Torres
        #print "Current norms ratio log2:", normsRatioLog2
370 62861417 Serge Torres
        scalingExpCandidate = normsRatioLog2 - maxExp 
371 62861417 Serge Torres
        #print "Current scaling exponent candidate:", scalingExpCandidate
372 62861417 Serge Torres
        if scalingExpCandidate < 0:
373 62861417 Serge Torres
            if -scalingExpCandidate > extraScalingExp:
374 62861417 Serge Torres
                extraScalingExp = -scalingExpCandidate
375 62861417 Serge Torres
    return extraScalingExp
376 62861417 Serge Torres
# End cvp_extra_function_scaling_exp.
377 9645ea29 Serge Torres
#
378 9645ea29 Serge Torres
def cvp_float_basis(monomialsList, pointsList, realField):
379 9645ea29 Serge Torres
    """
380 9645ea29 Serge Torres
    For a given monomials list and points list, compute the floating-point
381 9645ea29 Serge Torres
    basis matrix.
382 9645ea29 Serge Torres
    """
383 9645ea29 Serge Torres
    numRows    = len(monomialsList)
384 9645ea29 Serge Torres
    numCols    = len(pointsList)
385 9645ea29 Serge Torres
    if numRows == 0 or numCols == 0:
386 9645ea29 Serge Torres
        return matrix(realField, 0, 0)
387 9645ea29 Serge Torres
    #
388 9645ea29 Serge Torres
    floatBasis = matrix(realField, numRows, numCols)
389 9645ea29 Serge Torres
    for rIndex in xrange(0, numRows):
390 9645ea29 Serge Torres
        for cIndex in xrange(0, numCols):
391 9645ea29 Serge Torres
            floatBasis[rIndex,cIndex] = \
392 9645ea29 Serge Torres
                monomialsList[rIndex](realField(pointsList[cIndex]))
393 9645ea29 Serge Torres
    return floatBasis
394 9645ea29 Serge Torres
# End cvp_float_basis
395 9645ea29 Serge Torres
#
396 9645ea29 Serge Torres
def cvp_float_vector_for_approx(func, 
397 9645ea29 Serge Torres
                                basisPointsList,
398 9645ea29 Serge Torres
                                realField):
399 9645ea29 Serge Torres
    """
400 9645ea29 Serge Torres
    Compute a floating-point vector for the function and the points list.
401 9645ea29 Serge Torres
    """
402 9645ea29 Serge Torres
    #
403 9645ea29 Serge Torres
    ## Some local variables.
404 9645ea29 Serge Torres
    basisPointsNum = len(basisPointsList)
405 9645ea29 Serge Torres
    #
406 9645ea29 Serge Torres
    ##
407 9645ea29 Serge Torres
    vVect = vector(realField, basisPointsNum)
408 9645ea29 Serge Torres
    for vIndex in xrange(0,basisPointsNum):
409 9645ea29 Serge Torres
        vVect[vIndex] = \
410 9645ea29 Serge Torres
            func(basisPointsList[vIndex])
411 9645ea29 Serge Torres
    return vVect
412 9645ea29 Serge Torres
# End cvp_float_vector_for_approx.
413 9645ea29 Serge Torres
#
414 9645ea29 Serge Torres
def cvp_hkz_reduce(intBasis):
415 9645ea29 Serge Torres
    """
416 9645ea29 Serge Torres
    Thin and simplistic wrapper the HKZ function of the FP_LLL module.
417 9645ea29 Serge Torres
    """
418 9645ea29 Serge Torres
    fplllIntBasis = FP_LLL(intBasis)
419 9645ea29 Serge Torres
    fplllIntBasis.HKZ()
420 9645ea29 Serge Torres
    return fplllIntBasis._sage_()
421 9645ea29 Serge Torres
# End cvp_hkz_reduce.
422 9645ea29 Serge Torres
#
423 62861417 Serge Torres
def cvp_int_basis(floatBasis, 
424 62861417 Serge Torres
                  commonScalingExp, 
425 62861417 Serge Torres
                  extraScalingExpsList):
426 9645ea29 Serge Torres
    """
427 62861417 Serge Torres
    From the float basis, the common scaling factor and the extra exponents 
428 62861417 Serge Torres
    compute the integral basis.
429 9645ea29 Serge Torres
    """
430 62861417 Serge Torres
    ## Checking arguments.
431 62861417 Serge Torres
    if floatBasis.nrows() != len(extraScalingExpsList):
432 62861417 Serge Torres
        return None
433 9645ea29 Serge Torres
    intBasis = matrix(ZZ, floatBasis.nrows(), floatBasis.ncols())
434 9645ea29 Serge Torres
    for rIndex in xrange(0, floatBasis.nrows()):
435 9645ea29 Serge Torres
        for cIndex in xrange(0, floatBasis.ncols()):
436 9645ea29 Serge Torres
            intBasis[rIndex, cIndex] = \
437 9b0c03e7 Serge Torres
            (floatBasis[rIndex, cIndex] * \
438 9b0c03e7 Serge Torres
            2^(commonScalingExp + extraScalingExpsList[rIndex])).round()
439 9645ea29 Serge Torres
    return intBasis
440 9645ea29 Serge Torres
# End cvp_int_basis.
441 9645ea29 Serge Torres
#
442 62861417 Serge Torres
def cvp_int_vector_for_approx(floatVect, commonScalingExp, extraScalingExp):
443 9b0c03e7 Serge Torres
    """
444 9b0c03e7 Serge Torres
    Compute the integral version of the function vector.
445 9b0c03e7 Serge Torres
    """
446 62861417 Serge Torres
    totalScalingFactor = 2^(commonScalingExp + extraScalingExp)
447 9645ea29 Serge Torres
    intVect = vector(ZZ, len(floatVect))
448 9645ea29 Serge Torres
    for index in xrange(0, len(floatVect)):
449 9645ea29 Serge Torres
        intVect[index] = (floatVect[index] * totalScalingFactor).round()
450 9645ea29 Serge Torres
    return intVect
451 9645ea29 Serge Torres
# End cvp_int_vector_for_approx.
452 9645ea29 Serge Torres
#
453 9645ea29 Serge Torres
def cvp_lll_reduce(intBasis):
454 9645ea29 Serge Torres
    """
455 9645ea29 Serge Torres
    Thin and simplistic wrapper around the LLL function
456 9645ea29 Serge Torres
    """
457 9645ea29 Serge Torres
    return intBasis.LLL()
458 9645ea29 Serge Torres
# End cvp_lll_reduce.
459 9645ea29 Serge Torres
#
460 9645ea29 Serge Torres
def cvp_monomials_list(exponentsList, varName = None):
461 9645ea29 Serge Torres
    """
462 9645ea29 Serge Torres
    Create a list of monomials corresponding to the given exponentsList.
463 9645ea29 Serge Torres
    Monomials are defined as functions.
464 9645ea29 Serge Torres
    """
465 9645ea29 Serge Torres
    monomialsList = []
466 9645ea29 Serge Torres
    for exponent in exponentsList:
467 9645ea29 Serge Torres
        if varName is None:
468 9645ea29 Serge Torres
            monomialsList.append((x^exponent).function(x))
469 9645ea29 Serge Torres
        else:
470 9645ea29 Serge Torres
            monomialsList.append((varName^exponent).function(varName))
471 9645ea29 Serge Torres
    return monomialsList
472 9645ea29 Serge Torres
# End cvp_monomials_list.
473 9645ea29 Serge Torres
#
474 62861417 Serge Torres
def cvp_polynomial_coeffs_from_vect(cvpVectInBasis,
475 9cf1fb38 Serge Torres
                                    coeffsPrecList, 
476 9cf1fb38 Serge Torres
                                    minCoeffsExpList,
477 9cf1fb38 Serge Torres
                                    extraFuncScalingExp):
478 9cf1fb38 Serge Torres
    """
479 9cf1fb38 Serge Torres
    Computes polynomial coefficients out of the elements of the CVP vector.
480 9cf1fb38 Serge Torres
    @todo
481 9cf1fb38 Serge Torres
    Rewrite the code with a single exponentiation, at the very end.
482 9cf1fb38 Serge Torres
    """
483 62861417 Serge Torres
    numElements = len(cvpVectInBasis)
484 62861417 Serge Torres
    ## Arguments check.
485 62861417 Serge Torres
    if numElements != len(minCoeffsExpList) or \
486 62861417 Serge Torres
       numElements != len(coeffsPrecList):
487 62861417 Serge Torres
        return None
488 62861417 Serge Torres
    polynomialCoeffsList = []
489 62861417 Serge Torres
    for index in xrange(0, numElements):
490 62861417 Serge Torres
        currentCoeff = cvp_round_to_bits(cvpVectInBasis[index],
491 62861417 Serge Torres
                                         coeffsPrecList[index])
492 62861417 Serge Torres
        print "cvp_polynomial_coeffs - current coefficient rounded:", currentCoeff
493 62861417 Serge Torres
        currentCoeff *= 2^(minCoeffsExpList[index])
494 62861417 Serge Torres
        print "cvp_polynomial_coeffs - current coefficient scaled :", currentCoeff
495 62861417 Serge Torres
        currentCoeff *= 2^(-coeffsPrecList[index])
496 62861417 Serge Torres
        print "cvp_polynomial_coeffs - current coefficient prec corrected :", currentCoeff
497 62861417 Serge Torres
        currentCoeff *= 2^(-extraFuncScalingExp)
498 62861417 Serge Torres
        print "cvp_polynomial_coeffs - current coefficient extra func scaled :", currentCoeff
499 62861417 Serge Torres
        polynomialCoeffsList.append(currentCoeff)
500 62861417 Serge Torres
    return polynomialCoeffsList
501 62861417 Serge Torres
# En polynomial_coeffs_from_vect.
502 62861417 Serge Torres
#
503 9b0c03e7 Serge Torres
def cvp_polynomial_from_coeffs_and_exps(coeffsList, 
504 9b0c03e7 Serge Torres
                                        expsList, 
505 9b0c03e7 Serge Torres
                                        polyField = None,
506 9b0c03e7 Serge Torres
                                        theVar = None):
507 9b0c03e7 Serge Torres
    """
508 9b0c03e7 Serge Torres
    Build a polynomial in the classical monomials (possibly lacunary) basis 
509 9b0c03e7 Serge Torres
    from a list of coefficients and a list of exponents. The polynomial is in
510 9b0c03e7 Serge Torres
    the polynomial field given as argument.
511 9b0c03e7 Serge Torres
    """
512 9b0c03e7 Serge Torres
    if len(coeffsList) != len(expsList):
513 9b0c03e7 Serge Torres
        return None
514 9b0c03e7 Serge Torres
    ## If no variable is given, "x" is used.
515 9b0c03e7 Serge Torres
    ## If no polyField is given, we fall back on a polynomial field on RR.
516 9b0c03e7 Serge Torres
    if theVar is None:
517 9b0c03e7 Serge Torres
        if polyField is None:
518 9b0c03e7 Serge Torres
            theVar = x
519 9b0c03e7 Serge Torres
            polyField = RR[theVar]
520 9b0c03e7 Serge Torres
        else:
521 9b0c03e7 Serge Torres
            theVar = var(polyField.variable_name())
522 9b0c03e7 Serge Torres
    else: # theVar is set.
523 9b0c03e7 Serge Torres
        if polyField is None:
524 9b0c03e7 Serge Torres
            polyField = RR[theVar]
525 9b0c03e7 Serge Torres
        else: # Both the polyFiled and theVar are set: create a new polyField
526 9b0c03e7 Serge Torres
            # with theVar. The original polyField is not affected by the change.
527 9b0c03e7 Serge Torres
            polyField = polyField.change_var(theVar)  
528 9b0c03e7 Serge Torres
    ## Seed the polynomial.
529 9b0c03e7 Serge Torres
    poly = polyField(0)
530 9b0c03e7 Serge Torres
    ## Append the terms.
531 9b0c03e7 Serge Torres
    for coeff, exp in zip(coeffsList, expsList):
532 9b0c03e7 Serge Torres
        poly += polyField(coeff * theVar^exp)
533 9b0c03e7 Serge Torres
    return poly
534 9b0c03e7 Serge Torres
# End cvp_polynomial_from_coeffs_and_exps.
535 9b0c03e7 Serge Torres
#
536 9cf1fb38 Serge Torres
def cvp_remez_all_poly_error_func_maxis(funct, 
537 9b0c03e7 Serge Torres
                                        maxDegree, 
538 9b0c03e7 Serge Torres
                                        lowerBound, 
539 9b0c03e7 Serge Torres
                                        upperBound,
540 9b0c03e7 Serge Torres
                                        precsList, 
541 9b0c03e7 Serge Torres
                                        realField = None,
542 9b0c03e7 Serge Torres
                                        contFracMaxErr = None):
543 9b0c03e7 Serge Torres
    """
544 9b0c03e7 Serge Torres
    For a given function f, a degree and an interval, compute the 
545 9b0c03e7 Serge Torres
    maxima of the (f-remez_d(f)) function and those of the (f-truncRemez_d(f)) 
546 9b0c03e7 Serge Torres
    function over the interval.
547 9b0c03e7 Serge Torres
    """
548 9cf1fb38 Serge Torres
    ## If no realField argument is given try to retrieve it from the 
549 9cf1fb38 Serge Torres
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
550 9cf1fb38 Serge Torres
    if realField is None:
551 9cf1fb38 Serge Torres
        try:
552 9cf1fb38 Serge Torres
            ### Force failure if parent does not have prec() member.
553 9cf1fb38 Serge Torres
            lowerBound.parent().prec()
554 9cf1fb38 Serge Torres
            ### If no exception is thrown, set realField.
555 9cf1fb38 Serge Torres
            realField = lowerBound.parent()
556 9cf1fb38 Serge Torres
        except:
557 9cf1fb38 Serge Torres
            realField = RR
558 9cf1fb38 Serge Torres
    #print "Real field:", realField
559 9cf1fb38 Serge Torres
    funcSa         = func
560 9cf1fb38 Serge Torres
    funcAsStringSa = func._assume_str().replace("_SAGE_VAR_","",100)
561 9cf1fb38 Serge Torres
    print "Function as a string:", funcAsStringSa
562 9cf1fb38 Serge Torres
    ## Create the Sollya version of the function and compute the
563 9cf1fb38 Serge Torres
    #  Remez approximant
564 9cf1fb38 Serge Torres
    funcSo  = pobyso_parse_string(funcAsStringSa)
565 9cf1fb38 Serge Torres
    pStarSo = pobyso_remez_canonical_sa_so(funcAsStringSa, 
566 9cf1fb38 Serge Torres
                                           maxDegree, 
567 9cf1fb38 Serge Torres
                                           lowerBound,
568 9cf1fb38 Serge Torres
                                           upperBound)
569 9cf1fb38 Serge Torres
    ## Compute the error function and its derivative
570 9cf1fb38 Serge Torres
    ### First create the error function with copies since they are needed later.
571 9cf1fb38 Serge Torres
    errorFuncSo = sollya_lib_build_function_sub(sollya_lib_copy_obj(pStarSo), 
572 9cf1fb38 Serge Torres
                                                sollya_lib_copy_obj(funcSo))
573 9cf1fb38 Serge Torres
    intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound)
574 9cf1fb38 Serge Torres
    diffErrorFuncSo = pobyso_diff_so_so(errorFuncSo)
575 9cf1fb38 Serge Torres
    pobyso_clear_obj(errorFuncSo)
576 9cf1fb38 Serge Torres
    ## Compute the zeros of the derivative.
577 9cf1fb38 Serge Torres
    errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(diffErrorFuncSo, intervalSo)
578 9cf1fb38 Serge Torres
    pobyso_clear_obj(diffErrorFuncSo)
579 9cf1fb38 Serge Torres
    errorFuncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo)
580 9cf1fb38 Serge Torres
    pobyso_clear_obj(errorFuncZerosSo)
581 9cf1fb38 Serge Torres
    ## Compute the truncated Remez polynomial and the error function.
582 9cf1fb38 Serge Torres
    truncFormatListSo = pobyso_build_list_of_ints_sa_so(*precsList)
583 9cf1fb38 Serge Torres
    pTruncSo = pobyso_round_coefficients_so_so(pStarSo, truncFormatListSo)
584 9cf1fb38 Serge Torres
    pobyso_clear_obj(pStarSo)
585 9cf1fb38 Serge Torres
    ### Compute the error function. This time we consume both the function
586 9cf1fb38 Serge Torres
    #   and the polynomial.
587 9cf1fb38 Serge Torres
    errorFuncSo = sollya_lib_build_function_sub(pTruncSo, funcSo)
588 9cf1fb38 Serge Torres
    ## Compute the derivative.
589 9cf1fb38 Serge Torres
    diffErrorFuncSo = pobyso_diff_so_so(errorFuncSo)
590 9cf1fb38 Serge Torres
    pobyso_clear_obj(errorFuncSo)
591 9cf1fb38 Serge Torres
    ## Compute the zeros of the derivative.
592 9cf1fb38 Serge Torres
    errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(diffErrorFuncSo, intervalSo)
593 9cf1fb38 Serge Torres
    pobyso_clear_obj(diffErrorFuncSo)
594 9cf1fb38 Serge Torres
    pobyso_clear_obj(intervalSo)
595 9cf1fb38 Serge Torres
    errorFuncTruncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo)
596 9cf1fb38 Serge Torres
    pobyso_clear_obj(errorFuncZerosSo)
597 9cf1fb38 Serge Torres
    errorFuncZerosSa += errorFuncTruncZerosSa
598 9cf1fb38 Serge Torres
    errorFuncZerosSa.sort()
599 9cf1fb38 Serge Torres
    ## If required, convert the numbers to rational numbers.
600 9cf1fb38 Serge Torres
    if not contFracMaxErr is None:
601 9cf1fb38 Serge Torres
        for index in xrange(0, len(errorFuncZerosSa)):
602 9cf1fb38 Serge Torres
            errorFuncZerosSa[index] = \
603 9cf1fb38 Serge Torres
                errorFuncZerosSa[index].nearby_rational(contFracMaxErr)
604 9cf1fb38 Serge Torres
    return errorFuncZerosSa
605 9cf1fb38 Serge Torres
# End cvp_remez_all_poly_error_func_maxis.
606 9b0c03e7 Serge Torres
#
607 724064f1 Serge Torres
def cvp_remez_all_poly_error_func_zeros(funct, 
608 724064f1 Serge Torres
                                        maxDegree, 
609 724064f1 Serge Torres
                                        lowerBound, 
610 724064f1 Serge Torres
                                        upperBound,
611 724064f1 Serge Torres
                                        precsList, 
612 04d64614 Serge Torres
                                        realField = None,
613 04d64614 Serge Torres
                                        contFracMaxErr = None):
614 724064f1 Serge Torres
    """
615 724064f1 Serge Torres
    For a given function f, a degree and an interval, compute the 
616 04d64614 Serge Torres
    zeros of the (f-remez_d(f)) function and those of the (f-truncRemez_d(f)) 
617 9cf1fb38 Serge Torres
    function over the interval.
618 724064f1 Serge Torres
    """
619 04d64614 Serge Torres
    ## If no realField argument is given try to retrieve it from the 
620 04d64614 Serge Torres
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
621 04d64614 Serge Torres
    if realField is None:
622 04d64614 Serge Torres
        try:
623 04d64614 Serge Torres
            ### Force failure if parent does not have prec() member.
624 04d64614 Serge Torres
            lowerBound.parent().prec()
625 04d64614 Serge Torres
            ### If no exception is thrown, set realField.
626 04d64614 Serge Torres
            realField = lowerBound.parent()
627 04d64614 Serge Torres
        except:
628 04d64614 Serge Torres
            realField = RR
629 04d64614 Serge Torres
    #print "Real field:", realField
630 724064f1 Serge Torres
    funcSa         = func
631 724064f1 Serge Torres
    funcAsStringSa = func._assume_str().replace("_SAGE_VAR_","",100)
632 724064f1 Serge Torres
    print "Function as a string:", funcAsStringSa
633 724064f1 Serge Torres
    ## Create the Sollya version of the function and compute the
634 724064f1 Serge Torres
    #  Remez approximant
635 724064f1 Serge Torres
    funcSo  = pobyso_parse_string(funcAsStringSa)
636 724064f1 Serge Torres
    pStarSo = pobyso_remez_canonical_sa_so(funcAsStringSa, 
637 724064f1 Serge Torres
                                           maxDegree, 
638 724064f1 Serge Torres
                                           lowerBound,
639 724064f1 Serge Torres
                                           upperBound)
640 724064f1 Serge Torres
    ## Compute the zeroes of the error function.
641 724064f1 Serge Torres
    ### First create the error function with copies since they are needed later.
642 724064f1 Serge Torres
    errorFuncSo = sollya_lib_build_function_sub(sollya_lib_copy_obj(pStarSo), 
643 724064f1 Serge Torres
                                                sollya_lib_copy_obj(funcSo))
644 04d64614 Serge Torres
    intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound)
645 724064f1 Serge Torres
    errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(errorFuncSo, intervalSo)
646 724064f1 Serge Torres
    pobyso_clear_obj(errorFuncSo) # Clears funcSo and pStarSo as well.
647 724064f1 Serge Torres
    #print "Zeroes of the error function from Sollya:"
648 724064f1 Serge Torres
    #pobyso_autoprint(errorFuncZerosSo)
649 724064f1 Serge Torres
    errorFuncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo)
650 724064f1 Serge Torres
    pobyso_clear_obj(errorFuncZerosSo)
651 724064f1 Serge Torres
    #print "\nZeroes of the error function from Sage:"
652 724064f1 Serge Torres
    #print errorFuncZerosSa
653 724064f1 Serge Torres
    #
654 724064f1 Serge Torres
    ## Deal with the truncated polynomial now.
655 724064f1 Serge Torres
    ### Create the formats list. Notice the "*" before the list variable name.
656 724064f1 Serge Torres
    truncFormatListSo = pobyso_build_list_of_ints_sa_so(*precsList)
657 9b0c03e7 Serge Torres
    #print "Precisions list as Sollya object:", 
658 9cf1fb38 Serge Torres
    #pobyso_autoprint(truncFormatListSo)
659 724064f1 Serge Torres
    pTruncSo = pobyso_round_coefficients_so_so(pStarSo, truncFormatListSo)
660 9b0c03e7 Serge Torres
    #print "Truncated polynomial:", ; pobyso_autoprint(pTruncSo)
661 724064f1 Serge Torres
    ### Compute the error function. This time we consume both the function
662 724064f1 Serge Torres
    #   and the polynomial.
663 724064f1 Serge Torres
    errorFuncSo = sollya_lib_build_function_sub(pTruncSo, 
664 724064f1 Serge Torres
                                                funcSo)
665 724064f1 Serge Torres
    errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(errorFuncSo, intervalSo)
666 724064f1 Serge Torres
    pobyso_clear_obj(pStarSo)
667 9b0c03e7 Serge Torres
    #print "Zeroes of the error function for the truncated polynomial from Sollya:"
668 9cf1fb38 Serge Torres
    #pobyso_autoprint(errorFuncZerosSo)
669 724064f1 Serge Torres
    errorFuncTruncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo)
670 724064f1 Serge Torres
    pobyso_clear_obj(errorFuncZerosSo)
671 724064f1 Serge Torres
    ## Sollya objects clean up.
672 724064f1 Serge Torres
    pobyso_clear_obj(intervalSo)
673 724064f1 Serge Torres
    errorFuncZerosSa += errorFuncTruncZerosSa
674 724064f1 Serge Torres
    errorFuncZerosSa.sort()
675 04d64614 Serge Torres
    ## If required, convert the numbers to rational numbers.
676 04d64614 Serge Torres
    if not contFracMaxErr is None:
677 04d64614 Serge Torres
        for index in xrange(0, len(errorFuncZerosSa)):
678 04d64614 Serge Torres
            errorFuncZerosSa[index] = \
679 04d64614 Serge Torres
                errorFuncZerosSa[index].nearby_rational(contFracMaxErr)
680 04d64614 Serge Torres
    return errorFuncZerosSa
681 04d64614 Serge Torres
    #
682 04d64614 Serge Torres
# End remez_all_poly_error_func_zeros
683 04d64614 Serge Torres
#
684 04d64614 Serge Torres
def cvp_remez_poly_error_func_zeros(funct, 
685 04d64614 Serge Torres
                                    maxDegree, 
686 04d64614 Serge Torres
                                    lowerBound, 
687 04d64614 Serge Torres
                                    upperBound,
688 04d64614 Serge Torres
                                    realField = None,
689 04d64614 Serge Torres
                                    contFracMaxErr = None):
690 04d64614 Serge Torres
    """
691 04d64614 Serge Torres
    For a given function f, a degree and an interval, compute the 
692 04d64614 Serge Torres
    zeros of the (f-remez_d(f)) function.
693 04d64614 Serge Torres
    """
694 04d64614 Serge Torres
    ## If no realField argument is given try to retrieve it from the 
695 04d64614 Serge Torres
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
696 04d64614 Serge Torres
    if realField is None:
697 04d64614 Serge Torres
        try:
698 04d64614 Serge Torres
            ### Force failure if parent does not have prec() member.
699 04d64614 Serge Torres
            lowerBound.parent().prec()
700 04d64614 Serge Torres
            ### If no exception is thrown, set realField.
701 04d64614 Serge Torres
            realField = lowerBound.parent()
702 04d64614 Serge Torres
        except:
703 04d64614 Serge Torres
            realField = RR
704 04d64614 Serge Torres
    #print "Real field:", realField
705 04d64614 Serge Torres
    funcSa         = func
706 04d64614 Serge Torres
    funcAsStringSa = func._assume_str().replace("_SAGE_VAR_","",100)
707 04d64614 Serge Torres
    #print "Function as a string:", funcAsStringSa
708 04d64614 Serge Torres
    ## Create the Sollya version of the function and compute the
709 04d64614 Serge Torres
    #  Remez approximant
710 04d64614 Serge Torres
    funcSo  = pobyso_parse_string(funcAsStringSa)
711 04d64614 Serge Torres
    pStarSo = pobyso_remez_canonical_sa_so(funcAsStringSa, 
712 04d64614 Serge Torres
                                           maxDegree, 
713 04d64614 Serge Torres
                                           lowerBound,
714 04d64614 Serge Torres
                                           upperBound)
715 04d64614 Serge Torres
    ## Compute the zeroes of the error function.
716 04d64614 Serge Torres
    ### Error function creation consumes both pStarSo and funcSo.
717 04d64614 Serge Torres
    errorFuncSo = sollya_lib_build_function_sub(pStarSo, funcSo)
718 04d64614 Serge Torres
    intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound)
719 04d64614 Serge Torres
    errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(errorFuncSo, intervalSo)
720 04d64614 Serge Torres
    pobyso_clear_obj(errorFuncSo) # Clears funcSo and pStarSo as well.
721 04d64614 Serge Torres
    #print "Zeroes of the error function from Sollya:"
722 04d64614 Serge Torres
    #pobyso_autoprint(errorFuncZerosSo)
723 04d64614 Serge Torres
    errorFuncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo)
724 04d64614 Serge Torres
    pobyso_clear_obj(errorFuncZerosSo)
725 04d64614 Serge Torres
    ## Sollya objects clean up.
726 04d64614 Serge Torres
    pobyso_clear_obj(intervalSo)
727 04d64614 Serge Torres
    ## Converting to rational numbers, if required.
728 04d64614 Serge Torres
    if not contFracMaxErr is None:
729 04d64614 Serge Torres
        for index in xrange(0, len(errorFuncZerosSa)):
730 04d64614 Serge Torres
            errorFuncZerosSa[index] = \
731 04d64614 Serge Torres
                errorFuncZerosSa[index].nearby_rational(contFracMaxErr)
732 724064f1 Serge Torres
    return errorFuncZerosSa
733 724064f1 Serge Torres
    #
734 724064f1 Serge Torres
# End remez_poly_error_func_zeros
735 724064f1 Serge Torres
#
736 62861417 Serge Torres
def cvp_round_to_bits(num, numBits):
737 62861417 Serge Torres
    """
738 62861417 Serge Torres
    Round "num" to "numBits" bits.
739 62861417 Serge Torres
    @param num    : the number to round;
740 62861417 Serge Torres
    @param numBits: the number of bits to round to.
741 62861417 Serge Torres
    """
742 62861417 Serge Torres
    if num == 0:
743 62861417 Serge Torres
        return num
744 62861417 Serge Torres
    log2ofNum  = 0
745 62861417 Serge Torres
    numRounded = 0
746 62861417 Serge Torres
    ## Avoid conversion to floating-point if not necessary.
747 62861417 Serge Torres
    try:
748 62861417 Serge Torres
        log2OfNum = num.abs().log2()
749 62861417 Serge Torres
    except:
750 62861417 Serge Torres
        log2OfNum = RR(num).abs().log2()
751 62861417 Serge Torres
    ## Works equally well for num >= 1 and num < 1.
752 62861417 Serge Torres
    log2OfNum = ceil(log2OfNum)
753 62861417 Serge Torres
    # print "cvp_round_to_bits - Log2OfNum:", log2OfNum
754 62861417 Serge Torres
    divMult = log2OfNum - numBits
755 62861417 Serge Torres
    #print "cvp_round_to_bits - DivMult:", divMult
756 62861417 Serge Torres
    if divMult != 0:
757 62861417 Serge Torres
        numRounded = round(num/2^divMult) * 2^divMult
758 62861417 Serge Torres
    else:
759 62861417 Serge Torres
        numRounded = num
760 62861417 Serge Torres
    return numRounded
761 62861417 Serge Torres
# End cvp_round_to_bits
762 62861417 Serge Torres
#
763 9645ea29 Serge Torres
def cvp_vector_in_basis(vect, basis):
764 9645ea29 Serge Torres
    """
765 9645ea29 Serge Torres
    Compute the coordinates of "vect" in "basis" by
766 9645ea29 Serge Torres
    solving a linear system.
767 9cf1fb38 Serge Torres
    @param vect  the vector we want to compute the coordinates of
768 9645ea29 Serge Torres
                  in coordinates of the ambient space;
769 9cf1fb38 Serge Torres
    @param basis the basis we want to compute the coordinates in
770 9645ea29 Serge Torres
                  as a matrix relative to the ambient space.
771 9645ea29 Serge Torres
    """
772 9645ea29 Serge Torres
    ## Create the variables for the linear equations.
773 9645ea29 Serge Torres
    varDeclString = ""
774 9645ea29 Serge Torres
    basisIterationsRange = xrange(0, basis.nrows())
775 9645ea29 Serge Torres
    ### Building variables declaration string.
776 9645ea29 Serge Torres
    for index in basisIterationsRange:
777 9645ea29 Serge Torres
        varName = "a" + str(index)
778 9645ea29 Serge Torres
        if varDeclString == "":
779 9645ea29 Serge Torres
            varDeclString += varName
780 9645ea29 Serge Torres
        else:
781 9645ea29 Serge Torres
            varDeclString += "," + varName
782 9645ea29 Serge Torres
    ### Variables declaration
783 9645ea29 Serge Torres
    varsList = var(varDeclString)
784 9645ea29 Serge Torres
    sage_eval("var('" + varDeclString + "')")
785 9645ea29 Serge Torres
    ## Create the equations
786 9645ea29 Serge Torres
    equationString = ""
787 9645ea29 Serge Torres
    equationsList = []
788 9645ea29 Serge Torres
    for vIndex in xrange(0, len(vect)):
789 9645ea29 Serge Torres
        equationString = ""
790 9645ea29 Serge Torres
        for bIndex in basisIterationsRange:
791 9645ea29 Serge Torres
            if equationString != "":
792 9645ea29 Serge Torres
                equationString += "+"
793 9645ea29 Serge Torres
            equationString += str(varsList[bIndex]) + "*" + str(basis[bIndex,vIndex])
794 9645ea29 Serge Torres
        equationString += " == " + str(vect[vIndex])
795 9645ea29 Serge Torres
        equationsList.append(sage_eval(equationString))
796 9cf1fb38 Serge Torres
    ## Solve the equations system. The solution dictionary is needed
797 9645ea29 Serge Torres
    #  to recover the values of the solutions.
798 9645ea29 Serge Torres
    solutions = solve(equationsList,varsList, solution_dict=True)
799 9cf1fb38 Serge Torres
    ## This code is deactivated: did not solve the problem.
800 9cf1fb38 Serge Torres
    """
801 9cf1fb38 Serge Torres
    if len(solutions) == 0:
802 9cf1fb38 Serge Torres
        print "Trying Maxima to_poly_sove."
803 9cf1fb38 Serge Torres
        solutions = solve(equationsList,varsList, solution_dict=True, to_poly_solve = 'force')
804 9cf1fb38 Serge Torres
    """
805 9645ea29 Serge Torres
    #print "Solutions:", s
806 9645ea29 Serge Torres
    ## Recover solutions in rational components vector.
807 9645ea29 Serge Torres
    vectInBasis = vector(QQ, basis.nrows())
808 9645ea29 Serge Torres
    ### There can be several solution, in the general case.
809 9cf1fb38 Serge Torres
    #   Here, there is only one (or none). For each solution, each 
810 9645ea29 Serge Torres
    #   variable has to be searched for.
811 9645ea29 Serge Torres
    for sol in solutions:
812 9645ea29 Serge Torres
        for bIndex in basisIterationsRange:
813 9645ea29 Serge Torres
            vectInBasis[bIndex] = sol[varsList[bIndex]]
814 9645ea29 Serge Torres
    return vectInBasis
815 9645ea29 Serge Torres
# End cpv_vector_in_basis.
816 9645ea29 Serge Torres
#
817 9645ea29 Serge Torres
print "... functions for CVP loaded."