Statistiques
| Branche: | Révision :

cvp / src / functions_for_cvp.sage @ a0725e69

Historique | Voir | Annoter | Télécharger (47,52 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 94c8237b Serge Torres
sys.stderr.write("Functions for CVP loading...\n")
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 94c8237b 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 c7bf1784 Serge Torres
def cvp_chebyshev_maxis_1k(numPoints, realField, contFracMaxErr = None):
197 c7bf1784 Serge Torres
    """
198 c7bf1784 Serge Torres
    Compute the Chebyshev maxis for some polynomial degree (numPoints, for the
199 c7bf1784 Serge Torres
    zeros) scaled to the [lowerBound, upperBound] interval.
200 c7bf1784 Serge Torres
    The list is returned as row floating-point numbers is contFracMaxErr is None.
201 c7bf1784 Serge Torres
    Otherwise elements are transformed into rational numbers. 
202 c7bf1784 Serge Torres
    """
203 c7bf1784 Serge Torres
    if numPoints < 1:
204 c7bf1784 Serge Torres
        return None
205 c7bf1784 Serge Torres
    if numPoints == 0:
206 c7bf1784 Serge Torres
        return [0]
207 c7bf1784 Serge Torres
    ## Check that realField has a "prec()" member.
208 c7bf1784 Serge Torres
    try:
209 c7bf1784 Serge Torres
        realField.prec()
210 c7bf1784 Serge Torres
    except:
211 c7bf1784 Serge Torres
        return None
212 c7bf1784 Serge Torres
    #
213 c7bf1784 Serge Torres
    maxisList = []
214 c7bf1784 Serge Torres
    ## n extrema are given by a degree (n-1) Chebyshev polynomial.
215 c7bf1784 Serge Torres
    #  formulas: cos ((i * pi) / (numPoints - 1)) for i = 0,...,numPoints-1.
216 c7bf1784 Serge Torres
    #  Source: https://en.wikipedia.org/wiki/Chebyshev_polynomials
217 c7bf1784 Serge Torres
    for index in xrange(0, numPoints):
218 c7bf1784 Serge Torres
        ## When number of points is odd (then, the Chebyshev degree is odd two), 
219 c7bf1784 Serge Torres
        #  the central point is 0. */
220 c7bf1784 Serge Torres
        if (numPoints % 2 == 1) and ((2 * index + 1) == numPoints):
221 c7bf1784 Serge Torres
            if contFracMaxErr is None:
222 c7bf1784 Serge Torres
                maxisList.append(realField(0))
223 c7bf1784 Serge Torres
            else:
224 c7bf1784 Serge Torres
                maxisList.append(0)
225 c7bf1784 Serge Torres
        else:
226 c7bf1784 Serge Torres
            currentCheby = \
227 c7bf1784 Serge Torres
                ((realField(index) * realField(pi)) / 
228 c7bf1784 Serge Torres
                 realField(numPoints-1)).cos()
229 c7bf1784 Serge Torres
            #print  "Current Cheby:", currentCheby
230 c7bf1784 Serge Torres
            ## Result is negated to have an increasing order list.
231 c7bf1784 Serge Torres
            if contFracMaxErr is None:
232 c7bf1784 Serge Torres
                maxisList.append(-currentCheby)
233 c7bf1784 Serge Torres
            else:
234 c7bf1784 Serge Torres
                maxisList.append(-currentCheby.nearby_rational(contFracMaxErr))
235 c7bf1784 Serge Torres
            #print "Relative error:", (currentCheby/maxisList[index])
236 c7bf1784 Serge Torres
    return maxisList
237 c7bf1784 Serge Torres
# End cvp_chebyshev_maxis_1k.
238 c7bf1784 Serge Torres
#
239 c7bf1784 Serge Torres
def cvp_chebyshev_maxis_for_interval(lowerBound, 
240 c7bf1784 Serge Torres
                                     upperBound, 
241 c7bf1784 Serge Torres
                                     numPoints,
242 c7bf1784 Serge Torres
                                     realField = None, 
243 c7bf1784 Serge Torres
                                     contFracMaxErr = None):
244 c7bf1784 Serge Torres
    """
245 c7bf1784 Serge Torres
    Compute the Chebyshev maxis for some polynomial degree (numPoints, for the
246 c7bf1784 Serge Torres
    maxis) scaled to the [lowerBound, upperBound] interval.
247 c7bf1784 Serge Torres
    If no contFracMaxErr argument is given, we return the list as "raw"
248 c7bf1784 Serge Torres
    floating-points. Otherwise, rational numbers are returned.
249 c7bf1784 Serge Torres
    """
250 c7bf1784 Serge Torres
    ## Arguments check.
251 c7bf1784 Serge Torres
    if lowerBound >= upperBound:
252 c7bf1784 Serge Torres
        return None
253 c7bf1784 Serge Torres
    if numPoints < 1:
254 c7bf1784 Serge Torres
        return None
255 c7bf1784 Serge Torres
    ## If no realField argument is given try to retrieve it from the 
256 c7bf1784 Serge Torres
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
257 c7bf1784 Serge Torres
    if realField is None:
258 c7bf1784 Serge Torres
        try:
259 c7bf1784 Serge Torres
            ### Force failure if parent does not have prec() member.
260 c7bf1784 Serge Torres
            lowerBound.parent().prec()
261 c7bf1784 Serge Torres
            ### If no exception is thrown, set realField.
262 c7bf1784 Serge Torres
            realField = lowerBound.parent()
263 c7bf1784 Serge Torres
        except:
264 c7bf1784 Serge Torres
            realField = RR
265 c7bf1784 Serge Torres
    #print "Real field:", realField
266 c7bf1784 Serge Torres
    ## We want "raw"floating-point nodes to only have one final rounding.
267 c7bf1784 Serge Torres
    chebyshevMaxisList = \
268 c7bf1784 Serge Torres
        cvp_chebyshev_maxis_1k(numPoints, realField)
269 c7bf1784 Serge Torres
    scalingFactor, offset = cvp_affine_from_chebyshev(lowerBound, upperBound)
270 c7bf1784 Serge Torres
    for index in xrange(0, len(chebyshevMaxisList)):
271 c7bf1784 Serge Torres
        chebyshevMaxisList[index] = \
272 c7bf1784 Serge Torres
            chebyshevMaxisList[index] * scalingFactor + offset
273 c7bf1784 Serge Torres
        if not contFracMaxErr is None:
274 c7bf1784 Serge Torres
            chebyshevMaxisList[index] = \
275 c7bf1784 Serge Torres
                chebyshevMaxisList[index].nearby_rational(contFracMaxErr)
276 c7bf1784 Serge Torres
    return chebyshevMaxisList                                                             
277 c7bf1784 Serge Torres
# End cvp_chebyshev_maxis_for_interval.
278 c7bf1784 Serge Torres
#
279 04d64614 Serge Torres
def cvp_chebyshev_zeros_1k(numPoints, realField, contFracMaxErr = None):
280 04d64614 Serge Torres
    """
281 04d64614 Serge Torres
    Compute the Chebyshev zeros for some polynomial degree (numPoints, for the
282 04d64614 Serge Torres
    zeros) scaled to the [lowerBound, upperBound] interval.
283 04d64614 Serge Torres
    The list is returned as row floating-point numbers is contFracMaxErr is None.
284 04d64614 Serge Torres
    Otherwise elements are transformed into rational numbers. 
285 04d64614 Serge Torres
    """
286 04d64614 Serge Torres
    if numPoints < 1:
287 04d64614 Serge Torres
        return None
288 04d64614 Serge Torres
    if numPoints == 0:
289 04d64614 Serge Torres
        return [0]
290 04d64614 Serge Torres
    ## Check that realField has a "prec()" member.
291 04d64614 Serge Torres
    try:
292 04d64614 Serge Torres
        realField.prec()
293 04d64614 Serge Torres
    except:
294 04d64614 Serge Torres
        return None
295 04d64614 Serge Torres
    #
296 04d64614 Serge Torres
    zerosList = []
297 04d64614 Serge Torres
    ## formulas: cos (((2*i - 1) * pi) / (2*numPoints)) for i = 1,...,numPoints.
298 04d64614 Serge Torres
    #  If i is -1-shifted, as in the following loop, formula is 
299 04d64614 Serge Torres
    #  cos (((2*i + 1) * pi) / (2*numPoints)) for i = 0,...,numPoints-1.
300 04d64614 Serge Torres
    for index in xrange(0, numPoints):
301 04d64614 Serge Torres
        ## When number of points is odd (then, the Chebyshev degree is odd two), 
302 04d64614 Serge Torres
        #  the central point is 0. */
303 04d64614 Serge Torres
        if (numPoints % 2 == 1) and ((2 * index + 1) == numPoints):
304 04d64614 Serge Torres
            if contFracMaxErr is None:
305 04d64614 Serge Torres
                zerosList.append(realField(0))
306 04d64614 Serge Torres
            else:
307 04d64614 Serge Torres
                zerosList.append(0)
308 04d64614 Serge Torres
        else:
309 04d64614 Serge Torres
            currentCheby = \
310 04d64614 Serge Torres
                ((realField(2*index+1) * realField(pi)) / 
311 04d64614 Serge Torres
                 realField(2*numPoints)).cos()
312 04d64614 Serge Torres
            #print  "Current Cheby:", currentCheby
313 04d64614 Serge Torres
            ## Result is negated to have an increasing order list.
314 04d64614 Serge Torres
            if contFracMaxErr is None:
315 04d64614 Serge Torres
                zerosList.append(-currentCheby)
316 04d64614 Serge Torres
            else:
317 04d64614 Serge Torres
                zerosList.append(-currentCheby.nearby_rational(contFracMaxErr))
318 04d64614 Serge Torres
            #print "Relative error:", (currentCheby/zerosList[index])
319 04d64614 Serge Torres
    return zerosList
320 04d64614 Serge Torres
# End cvp_chebyshev_zeros_1k.
321 04d64614 Serge Torres
#
322 04d64614 Serge Torres
def cvp_chebyshev_zeros_for_interval(lowerBound, 
323 04d64614 Serge Torres
                                     upperBound, 
324 04d64614 Serge Torres
                                     numPoints,
325 04d64614 Serge Torres
                                     realField = None, 
326 04d64614 Serge Torres
                                     contFracMaxErr = None):
327 04d64614 Serge Torres
    """
328 04d64614 Serge Torres
    Compute the Chebyshev zeros for some polynomial degree (numPoints, for the
329 04d64614 Serge Torres
    zeros) scaled to the [lowerBound, upperBound] interval.
330 04d64614 Serge Torres
    If no contFracMaxErr argument is given, we return the list as "raw"
331 04d64614 Serge Torres
    floating-points. Otherwise, rational numbers are returned.
332 04d64614 Serge Torres
    """
333 04d64614 Serge Torres
    ## Arguments check.
334 04d64614 Serge Torres
    if lowerBound >= upperBound:
335 04d64614 Serge Torres
        return None
336 04d64614 Serge Torres
    if numPoints < 1:
337 04d64614 Serge Torres
        return None
338 04d64614 Serge Torres
    ## If no realField argument is given try to retrieve it from the 
339 04d64614 Serge Torres
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
340 04d64614 Serge Torres
    if realField is None:
341 04d64614 Serge Torres
        try:
342 04d64614 Serge Torres
            ### Force failure if parent does not have prec() member.
343 04d64614 Serge Torres
            lowerBound.parent().prec()
344 04d64614 Serge Torres
            ### If no exception is thrown, set realField.
345 04d64614 Serge Torres
            realField = lowerBound.parent()
346 04d64614 Serge Torres
        except:
347 04d64614 Serge Torres
            realField = RR
348 04d64614 Serge Torres
    #print "Real field:", realField
349 04d64614 Serge Torres
    ## We want "raw"floating-point nodes to only have one final rounding.
350 04d64614 Serge Torres
    chebyshevZerosList = \
351 04d64614 Serge Torres
        cvp_chebyshev_zeros_1k(numPoints, realField)
352 04d64614 Serge Torres
    scalingFactor, offset = cvp_affine_from_chebyshev(lowerBound, upperBound)
353 04d64614 Serge Torres
    for index in xrange(0, len(chebyshevZerosList)):
354 04d64614 Serge Torres
        chebyshevZerosList[index] = \
355 04d64614 Serge Torres
            chebyshevZerosList[index] * scalingFactor + offset
356 04d64614 Serge Torres
        if not contFracMaxErr is None:
357 04d64614 Serge Torres
            chebyshevZerosList[index] = \
358 04d64614 Serge Torres
                chebyshevZerosList[index].nearby_rational(contFracMaxErr)
359 04d64614 Serge Torres
    return chebyshevZerosList                                                             
360 04d64614 Serge Torres
# End cvp_chebyshev_zeros_for_interval.
361 04d64614 Serge Torres
#
362 62861417 Serge Torres
def cvp_common_scaling_exp(precision, 
363 62861417 Serge Torres
                           precisionFraction = None):
364 9645ea29 Serge Torres
    """
365 9645ea29 Serge Torres
    Compute the common scaling factor (a power of 2).
366 62861417 Serge Torres
    The exponent is a fraction of the precision;
367 62861417 Serge Torres
    A extra factor is computed for the vector,
368 62861417 Serge Torres
    exra factors are computed for the basis vectors, all in the corresponding
369 62861417 Serge Torres
    functions.
370 9645ea29 Serge Torres
    """
371 9645ea29 Serge Torres
    ## Set a default value for the precisionFraction to 1/2.
372 9645ea29 Serge Torres
    if precisionFraction is None:
373 62861417 Serge Torres
        precisionFraction = 3/4
374 62861417 Serge Torres
    """
375 9645ea29 Serge Torres
    minBasisVectsNorm = oo
376 9645ea29 Serge Torres
    currentNorm = 0
377 9645ea29 Serge Torres
    for vect in floatBasis.rows():
378 9645ea29 Serge Torres
        currentNorm = vect.norm()
379 9645ea29 Serge Torres
        print "Current norm:", currentNorm
380 9645ea29 Serge Torres
        if currentNorm < minBasisVectsNorm:
381 9645ea29 Serge Torres
            minBasisVectsNorm = currentNorm
382 9645ea29 Serge Torres
    currentNorm = funcVect.norm()
383 9645ea29 Serge Torres
    print "Current norm:", currentNorm
384 9645ea29 Serge Torres
    if currentNorm < minBasisVectsNorm:
385 9645ea29 Serge Torres
        minBasisVectsNorm = currentNorm
386 9645ea29 Serge Torres
    ## Check if a push is need because the smallest norm is below 0.    
387 9645ea29 Serge Torres
    powerForMinNorm = floor(log(minBasisVectsNorm)/log2)
388 9645ea29 Serge Torres
    print "Power for min norm :", powerForMinNorm
389 9645ea29 Serge Torres
    print "Power for precision:", ceil(precision*precisionFraction)
390 9645ea29 Serge Torres
    if powerForMinNorm < 0:
391 9645ea29 Serge Torres
        return 2^(ceil(precision*precisionFraction) - powerFromMinNorm)
392 9645ea29 Serge Torres
    else:
393 62861417 Serge Torres
    """
394 62861417 Serge Torres
    return ceil(precision * precisionFraction)
395 9645ea29 Serge Torres
# End cvp_common_scaling_factor.
396 9645ea29 Serge Torres
#
397 e2eb9ccc Serge Torres
def cvp_cvp_polynomial(func, 
398 e2eb9ccc Serge Torres
                       lowerBound, 
399 e2eb9ccc Serge Torres
                       upperBound,
400 e2eb9ccc Serge Torres
                       coeffsExpList,
401 e2eb9ccc Serge Torres
                       coeffsPrecList, 
402 e2eb9ccc Serge Torres
                       minCoeffsBoundExpList, 
403 e2eb9ccc Serge Torres
                       maxCoeffsBoundExpList,
404 e2eb9ccc Serge Torres
                       pointsList,
405 e2eb9ccc Serge Torres
                       realField):
406 e2eb9ccc Serge Torres
    """
407 e2eb9ccc Serge Torres
    Compute a polynomial based on a CVP vector for a function approximation. 
408 e2eb9ccc Serge Torres
    """
409 e2eb9ccc Serge Torres
    ## Build the basis for CVP.
410 e2eb9ccc Serge Torres
    ### Common scaling exponent.
411 e2eb9ccc Serge Torres
    commonScalingExp = cvp_common_scaling_exp(realField.prec())
412 e2eb9ccc Serge Torres
    ### Monomials list derived from exponenets list.
413 e2eb9ccc Serge Torres
    monomialsList = cvp_monomials_list(coeffsExpList)
414 e2eb9ccc Serge Torres
    ### Float basis first
415 e2eb9ccc Serge Torres
    floatBasis = cvp_float_basis(monomialsList, pointsList, realField)
416 e2eb9ccc Serge Torres
    ### Integral basis.
417 e2eb9ccc Serge Torres
    extraScalingExpsList = \
418 e2eb9ccc Serge Torres
        cvp_extra_basis_scaling_exps(coeffsPrecList, minCoeffsBoundExpList)
419 e2eb9ccc Serge Torres
    intBasis = \
420 e2eb9ccc Serge Torres
        cvp_int_basis(floatBasis, commonScalingExp, extraScalingExpsList)
421 e2eb9ccc Serge Torres
    ### The reduced basis.
422 e2eb9ccc Serge Torres
    redIntBasis = cvp_lll_reduce(intBasis)
423 e2eb9ccc Serge Torres
    ### The reduced basis GSO.
424 e2eb9ccc Serge Torres
    (redIntBasisGso, mu) = redIntBasis.gram_schmidt()
425 e2eb9ccc Serge Torres
    ## Function vector.
426 e2eb9ccc Serge Torres
    #### Floating-point vector.
427 e2eb9ccc Serge Torres
    floatFuncVect = \
428 e2eb9ccc Serge Torres
        cvp_float_vector_for_approx(func, pointsList, realField)
429 e2eb9ccc Serge Torres
    extraFuncScalingExp = \
430 e2eb9ccc Serge Torres
        cvp_extra_function_scaling_exp(floatBasis, 
431 e2eb9ccc Serge Torres
                                       floatFuncVect, 
432 e2eb9ccc Serge Torres
                                       maxCoeffsBoundExpList)
433 e2eb9ccc Serge Torres
    #### Integral vector.
434 e2eb9ccc Serge Torres
    intFuncVect   = \
435 e2eb9ccc Serge Torres
        cvp_int_vector_for_approx(floatFuncVect, 
436 e2eb9ccc Serge Torres
                                  commonScalingExp, 
437 e2eb9ccc Serge Torres
                                  extraFuncScalingExp)
438 e2eb9ccc Serge Torres
    ## CPV vector
439 e2eb9ccc Serge Torres
    ### In ambient basis.
440 e2eb9ccc Serge Torres
    cvpVectInAmbient = cvp_babai(redIntBasis, redIntBasisGso, intFuncVect)
441 e2eb9ccc Serge Torres
    ### In intBasis.
442 e2eb9ccc Serge Torres
    cvpVectInIntBasis = cvp_vector_in_basis(cvpVectInAmbient, intBasis)
443 e2eb9ccc Serge Torres
    ## Polynomial coefficients
444 e2eb9ccc Serge Torres
    cvpPolynomialCoeffs = \
445 e2eb9ccc Serge Torres
        cvp_polynomial_coeffs_from_vect(cvpVectInIntBasis, 
446 e2eb9ccc Serge Torres
                                        coeffsPrecList, 
447 e2eb9ccc Serge Torres
                                        minCoeffsBoundExpList, 
448 e2eb9ccc Serge Torres
                                        extraFuncScalingExp)
449 e2eb9ccc Serge Torres
    #print "CVP polynomial coefficients:"
450 e2eb9ccc Serge Torres
    #print cvpPolynomialCoeffs
451 e2eb9ccc Serge Torres
    ## Polynomial in Sage.
452 e2eb9ccc Serge Torres
    cvpPolySa =  \
453 e2eb9ccc Serge Torres
        cvp_polynomial_from_coeffs_and_exps(cvpPolynomialCoeffs,
454 e2eb9ccc Serge Torres
                                            coeffsExpList,
455 e2eb9ccc Serge Torres
                                            realField[x])
456 e2eb9ccc Serge Torres
    #print cvpPolySa
457 e2eb9ccc Serge Torres
    return cvpPolySa
458 e2eb9ccc Serge Torres
# End cvp_cvp_polynomial.
459 e2eb9ccc Serge Torres
#
460 724064f1 Serge Torres
def cvp_evaluation_points_list(funct, 
461 724064f1 Serge Torres
                               maxDegree, 
462 724064f1 Serge Torres
                               lowerBound, 
463 724064f1 Serge Torres
                               upperBound, 
464 724064f1 Serge Torres
                               realField = None):
465 724064f1 Serge Torres
    """
466 724064f1 Serge Torres
    Compute a list of points for the vector creation.
467 724064f1 Serge Torres
    Strategy:
468 724064f1 Serge Torres
    - compute the zeros of the function-remez;
469 724064f1 Serge Torres
    - compute the zeros of the function-rounded_remez;
470 724064f1 Serge Torres
    - compute the Chebyshev points.
471 724064f1 Serge Torres
    Merge the whole thing.
472 724064f1 Serge Torres
    """
473 724064f1 Serge Torres
    
474 724064f1 Serge Torres
# End cvp_evaluation_points_list.
475 724064f1 Serge Torres
#
476 62861417 Serge Torres
def cvp_extra_basis_scaling_exps(precsList, minExponentsList):
477 9cf1fb38 Serge Torres
    """
478 9cf1fb38 Serge Torres
    Computes the exponents for the extra scaling down of the elements of the
479 9cf1fb38 Serge Torres
    basis.
480 9cf1fb38 Serge Torres
    This extra scaling down is necessary when there are elements of the 
481 9cf1fb38 Serge Torres
    basis that have negative exponents.
482 9cf1fb38 Serge Torres
    """
483 62861417 Serge Torres
    extraScalingExpsList = []
484 62861417 Serge Torres
    for minExp, prec in zip(minExponentsList, precsList):
485 62861417 Serge Torres
        if minExp - prec < 0:
486 62861417 Serge Torres
            extraScalingExpsList.append(minExp - prec)
487 62861417 Serge Torres
        else:
488 62861417 Serge Torres
            extraScalingExpsList.append(0)
489 62861417 Serge Torres
    return extraScalingExpsList
490 62861417 Serge Torres
# End cvp_extra_basis_scaling_exps.
491 62861417 Serge Torres
#
492 62861417 Serge Torres
def cvp_extra_function_scaling_exp(floatBasis,
493 62861417 Serge Torres
                                   floatFuncVect,
494 62861417 Serge Torres
                                   maxExponentsList):
495 9645ea29 Serge Torres
    """
496 62861417 Serge Torres
    Compute the extra scaling exponent for the function vector in ordre to 
497 62861417 Serge Torres
    guarantee that the maximum exponent can be reached for each element of the
498 62861417 Serge Torres
    basis.
499 9645ea29 Serge Torres
    """
500 62861417 Serge Torres
    ## Check arguments
501 9645ea29 Serge Torres
    if floatBasis.nrows() == 0 or \
502 9645ea29 Serge Torres
       floatBasis.ncols() == 0 or \
503 62861417 Serge Torres
       len(floatFuncVect)      == 0:
504 62861417 Serge Torres
        return 1
505 62861417 Serge Torres
    if len(maxExponentsList) != floatBasis.nrows():
506 62861417 Serge Torres
        return None
507 62861417 Serge Torres
    ## Compute the log of the norm of the function vector.
508 62861417 Serge Torres
    funcVectNormLog  = log(floatFuncVect.norm())
509 9645ea29 Serge Torres
    ## Compute the extra scaling factor for each vector of the basis.
510 62861417 Serge Torres
    #  for norms ratios an maxExponentsList. 
511 62861417 Serge Torres
    extraScalingExp = 0
512 62861417 Serge Torres
    for (row, maxExp) in zip(floatBasis.rows(),maxExponentsList):
513 62861417 Serge Torres
        rowNormLog     = log(row.norm())
514 62861417 Serge Torres
        normsRatioLog2 = floor((funcVectNormLog - rowNormLog) / log2) 
515 62861417 Serge Torres
        #print "Current norms ratio log2:", normsRatioLog2
516 62861417 Serge Torres
        scalingExpCandidate = normsRatioLog2 - maxExp 
517 62861417 Serge Torres
        #print "Current scaling exponent candidate:", scalingExpCandidate
518 62861417 Serge Torres
        if scalingExpCandidate < 0:
519 62861417 Serge Torres
            if -scalingExpCandidate > extraScalingExp:
520 62861417 Serge Torres
                extraScalingExp = -scalingExpCandidate
521 62861417 Serge Torres
    return extraScalingExp
522 62861417 Serge Torres
# End cvp_extra_function_scaling_exp.
523 9645ea29 Serge Torres
#
524 2669308a Serge Torres
def cvp_filter_out_undefined_image(initialPointList, func):
525 2669308a Serge Torres
    """
526 2669308a Serge Torres
    Fom the initial list and function, built a list of points which have a
527 2669308a Serge Torres
    defined image.
528 2669308a Serge Torres
    """
529 2669308a Serge Torres
    finalPointsList = []
530 2669308a Serge Torres
    for iterPoint in initialPointList:
531 2669308a Serge Torres
        try:
532 2669308a Serge Torres
            finalPointsList.append(func(iterPoint))
533 2669308a Serge Torres
            #print "cfoui - Point", iterPoint, "done."
534 2669308a Serge Torres
        except ValueError:
535 2669308a Serge Torres
            pass
536 2669308a Serge Torres
            #print "cfoui - Point", iterPoint, "failed."
537 2669308a Serge Torres
    return finalPointsList
538 2669308a Serge Torres
# End    cvp_filter_out_undefined_image
539 2669308a Serge Torres
 
540 9645ea29 Serge Torres
def cvp_float_basis(monomialsList, pointsList, realField):
541 9645ea29 Serge Torres
    """
542 9645ea29 Serge Torres
    For a given monomials list and points list, compute the floating-point
543 9645ea29 Serge Torres
    basis matrix.
544 9645ea29 Serge Torres
    """
545 9645ea29 Serge Torres
    numRows    = len(monomialsList)
546 9645ea29 Serge Torres
    numCols    = len(pointsList)
547 9645ea29 Serge Torres
    if numRows == 0 or numCols == 0:
548 9645ea29 Serge Torres
        return matrix(realField, 0, 0)
549 9645ea29 Serge Torres
    #
550 9645ea29 Serge Torres
    floatBasis = matrix(realField, numRows, numCols)
551 9645ea29 Serge Torres
    for rIndex in xrange(0, numRows):
552 9645ea29 Serge Torres
        for cIndex in xrange(0, numCols):
553 9645ea29 Serge Torres
            floatBasis[rIndex,cIndex] = \
554 9645ea29 Serge Torres
                monomialsList[rIndex](realField(pointsList[cIndex]))
555 9645ea29 Serge Torres
    return floatBasis
556 9645ea29 Serge Torres
# End cvp_float_basis
557 9645ea29 Serge Torres
#
558 9645ea29 Serge Torres
def cvp_float_vector_for_approx(func, 
559 9645ea29 Serge Torres
                                basisPointsList,
560 9645ea29 Serge Torres
                                realField):
561 9645ea29 Serge Torres
    """
562 9645ea29 Serge Torres
    Compute a floating-point vector for the function and the points list.
563 9645ea29 Serge Torres
    """
564 9645ea29 Serge Torres
    #
565 9645ea29 Serge Torres
    ## Some local variables.
566 9645ea29 Serge Torres
    basisPointsNum = len(basisPointsList)
567 9645ea29 Serge Torres
    #
568 2669308a Serge Torres
    floatVector = vector(realField, basisPointsNum)
569 9645ea29 Serge Torres
    ##
570 9645ea29 Serge Torres
    for vIndex in xrange(0,basisPointsNum):
571 2669308a Serge Torres
        ### We assume the all for all points their image is defined.
572 2669308a Serge Torres
        floatVector[vIndex] = \
573 2669308a Serge Torres
                func(basisPointsList[vIndex])
574 2669308a Serge Torres
    return floatVector
575 9645ea29 Serge Torres
# End cvp_float_vector_for_approx.
576 9645ea29 Serge Torres
#
577 2669308a Serge Torres
def cvp_func_abs_max_for_points(func, pointsList, realField):
578 e2eb9ccc Serge Torres
    """
579 e2eb9ccc Serge Torres
    Compute the maximum absolute value of a function for a list of 
580 e2eb9ccc Serge Torres
    points.
581 e2eb9ccc Serge Torres
    If several points yield the same value and this value is the maximum,
582 1c8b6220 Serge Torres
    the last visited one is returned.
583 e2eb9ccc Serge Torres
    @return (theMaxPoint, theMaxValue) 
584 e2eb9ccc Serge Torres
    """
585 e2eb9ccc Serge Torres
    evalDict = dict()
586 1c8b6220 Serge Torres
    #
587 1c8b6220 Serge Torres
    ## An empty points list is really an error. We cannot return an empty tuple.
588 e2eb9ccc Serge Torres
    if len(pointsList) == 0:
589 e2eb9ccc Serge Torres
        return None
590 e2eb9ccc Serge Torres
    #
591 e2eb9ccc Serge Torres
    for pt in pointsList:
592 2669308a Serge Torres
        try:
593 2669308a Serge Torres
            evalDict[abs(realField(func(pt)))] = realField(pt)
594 2669308a Serge Torres
            #print "cfamfp - point:", realField(pt) , "- image:", abs(realField(func(pt)))
595 2669308a Serge Torres
        except ValueError:
596 2669308a Serge Torres
            pass
597 e2eb9ccc Serge Torres
    maxAbs = max(evalDict.keys())
598 2669308a Serge Torres
    #print "cfamfp - maxAbs:", maxAbs, evalDict[maxAbs]
599 e2eb9ccc Serge Torres
    return (evalDict[maxAbs], maxAbs)
600 e2eb9ccc Serge Torres
# End cvp_func_abs_max_for_points
601 e2eb9ccc Serge Torres
#
602 9645ea29 Serge Torres
def cvp_hkz_reduce(intBasis):
603 9645ea29 Serge Torres
    """
604 2669308a Serge Torres
    Thin and simplistic wrapper on the HKZ function of the FP_LLL module.
605 9645ea29 Serge Torres
    """
606 9645ea29 Serge Torres
    fplllIntBasis = FP_LLL(intBasis)
607 9645ea29 Serge Torres
    fplllIntBasis.HKZ()
608 9645ea29 Serge Torres
    return fplllIntBasis._sage_()
609 9645ea29 Serge Torres
# End cvp_hkz_reduce.
610 9645ea29 Serge Torres
#
611 62861417 Serge Torres
def cvp_int_basis(floatBasis, 
612 62861417 Serge Torres
                  commonScalingExp, 
613 62861417 Serge Torres
                  extraScalingExpsList):
614 9645ea29 Serge Torres
    """
615 62861417 Serge Torres
    From the float basis, the common scaling factor and the extra exponents 
616 62861417 Serge Torres
    compute the integral basis.
617 9645ea29 Serge Torres
    """
618 62861417 Serge Torres
    ## Checking arguments.
619 62861417 Serge Torres
    if floatBasis.nrows() != len(extraScalingExpsList):
620 62861417 Serge Torres
        return None
621 9645ea29 Serge Torres
    intBasis = matrix(ZZ, floatBasis.nrows(), floatBasis.ncols())
622 9645ea29 Serge Torres
    for rIndex in xrange(0, floatBasis.nrows()):
623 9645ea29 Serge Torres
        for cIndex in xrange(0, floatBasis.ncols()):
624 9645ea29 Serge Torres
            intBasis[rIndex, cIndex] = \
625 9b0c03e7 Serge Torres
            (floatBasis[rIndex, cIndex] * \
626 9b0c03e7 Serge Torres
            2^(commonScalingExp + extraScalingExpsList[rIndex])).round()
627 9645ea29 Serge Torres
    return intBasis
628 9645ea29 Serge Torres
# End cvp_int_basis.
629 9645ea29 Serge Torres
#
630 62861417 Serge Torres
def cvp_int_vector_for_approx(floatVect, commonScalingExp, extraScalingExp):
631 9b0c03e7 Serge Torres
    """
632 9b0c03e7 Serge Torres
    Compute the integral version of the function vector.
633 9b0c03e7 Serge Torres
    """
634 62861417 Serge Torres
    totalScalingFactor = 2^(commonScalingExp + extraScalingExp)
635 9645ea29 Serge Torres
    intVect = vector(ZZ, len(floatVect))
636 9645ea29 Serge Torres
    for index in xrange(0, len(floatVect)):
637 9645ea29 Serge Torres
        intVect[index] = (floatVect[index] * totalScalingFactor).round()
638 9645ea29 Serge Torres
    return intVect
639 9645ea29 Serge Torres
# End cvp_int_vector_for_approx.
640 9645ea29 Serge Torres
#
641 9645ea29 Serge Torres
def cvp_lll_reduce(intBasis):
642 9645ea29 Serge Torres
    """
643 9645ea29 Serge Torres
    Thin and simplistic wrapper around the LLL function
644 9645ea29 Serge Torres
    """
645 9645ea29 Serge Torres
    return intBasis.LLL()
646 9645ea29 Serge Torres
# End cvp_lll_reduce.
647 9645ea29 Serge Torres
#
648 9645ea29 Serge Torres
def cvp_monomials_list(exponentsList, varName = None):
649 9645ea29 Serge Torres
    """
650 9645ea29 Serge Torres
    Create a list of monomials corresponding to the given exponentsList.
651 9645ea29 Serge Torres
    Monomials are defined as functions.
652 9645ea29 Serge Torres
    """
653 9645ea29 Serge Torres
    monomialsList = []
654 9645ea29 Serge Torres
    for exponent in exponentsList:
655 9645ea29 Serge Torres
        if varName is None:
656 9645ea29 Serge Torres
            monomialsList.append((x^exponent).function(x))
657 9645ea29 Serge Torres
        else:
658 9645ea29 Serge Torres
            monomialsList.append((varName^exponent).function(varName))
659 9645ea29 Serge Torres
    return monomialsList
660 9645ea29 Serge Torres
# End cvp_monomials_list.
661 9645ea29 Serge Torres
#
662 62861417 Serge Torres
def cvp_polynomial_coeffs_from_vect(cvpVectInBasis,
663 9cf1fb38 Serge Torres
                                    coeffsPrecList, 
664 9cf1fb38 Serge Torres
                                    minCoeffsExpList,
665 9cf1fb38 Serge Torres
                                    extraFuncScalingExp):
666 9cf1fb38 Serge Torres
    """
667 9cf1fb38 Serge Torres
    Computes polynomial coefficients out of the elements of the CVP vector.
668 9cf1fb38 Serge Torres
    @todo
669 9cf1fb38 Serge Torres
    Rewrite the code with a single exponentiation, at the very end.
670 9cf1fb38 Serge Torres
    """
671 62861417 Serge Torres
    numElements = len(cvpVectInBasis)
672 62861417 Serge Torres
    ## Arguments check.
673 62861417 Serge Torres
    if numElements != len(minCoeffsExpList) or \
674 62861417 Serge Torres
       numElements != len(coeffsPrecList):
675 62861417 Serge Torres
        return None
676 62861417 Serge Torres
    polynomialCoeffsList = []
677 62861417 Serge Torres
    for index in xrange(0, numElements):
678 62861417 Serge Torres
        currentCoeff = cvp_round_to_bits(cvpVectInBasis[index],
679 62861417 Serge Torres
                                         coeffsPrecList[index])
680 e2eb9ccc Serge Torres
        #print "cvp_polynomial_coeffs - current coefficient rounded:", currentCoeff
681 62861417 Serge Torres
        currentCoeff *= 2^(minCoeffsExpList[index])
682 e2eb9ccc Serge Torres
        #print "cvp_polynomial_coeffs - current coefficient scaled :", currentCoeff
683 62861417 Serge Torres
        currentCoeff *= 2^(-coeffsPrecList[index])
684 e2eb9ccc Serge Torres
        #print "cvp_polynomial_coeffs - current coefficient prec corrected :", currentCoeff
685 62861417 Serge Torres
        currentCoeff *= 2^(-extraFuncScalingExp)
686 e2eb9ccc Serge Torres
        #print "cvp_polynomial_coeffs - current coefficient extra func scaled :", currentCoeff
687 62861417 Serge Torres
        polynomialCoeffsList.append(currentCoeff)
688 62861417 Serge Torres
    return polynomialCoeffsList
689 62861417 Serge Torres
# En polynomial_coeffs_from_vect.
690 62861417 Serge Torres
#
691 9c97e92f Serge Torres
def cvp_polynomial_error_func_maxis(funcSa,
692 9c97e92f Serge Torres
                                    polySa, 
693 9c97e92f Serge Torres
                                    lowerBoundSa, 
694 9c97e92f Serge Torres
                                    upperBoundSa,
695 9c97e92f Serge Torres
                                    realField = None,
696 9c97e92f Serge Torres
                                    contFracMaxErr = None):
697 9c97e92f Serge Torres
    """
698 9c97e92f Serge Torres
    For a given function, approximation polynomial and interval (given 
699 9c97e92f Serge Torres
    as bounds) compute the maxima of the functSa - polySo on the interval.
700 9c97e92f Serge Torres
    Also computes the infnorm of the error function.
701 9c97e92f Serge Torres
    """
702 9c97e92f Serge Torres
    ## Arguments check.
703 9c97e92f Serge Torres
    # @todo.
704 9c97e92f Serge Torres
    ## If no realField argument is given try to retrieve it from the 
705 9c97e92f Serge Torres
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
706 9c97e92f Serge Torres
    if realField is None:
707 9c97e92f Serge Torres
        try:
708 9c97e92f Serge Torres
            ### Force failure if parent does not have prec() member.
709 9c97e92f Serge Torres
            lowerBound.parent().prec()
710 9c97e92f Serge Torres
            ### If no exception is thrown, set realField.
711 9c97e92f Serge Torres
            realField = lowerBound.parent()
712 9c97e92f Serge Torres
        except:
713 9c97e92f Serge Torres
            realField = RR
714 9c97e92f Serge Torres
    #print "Real field:", realField
715 9c97e92f Serge Torres
    ## Compute the Sollya version of the function.
716 9c97e92f Serge Torres
    funcAsStringSa = funcSa._assume_str().replace("_SAGE_VAR_","",100)
717 3296902f Serge Torres
    #print "cpefa:", funcAsStringSa
718 9c97e92f Serge Torres
    funcSo  = pobyso_parse_string(funcAsStringSa)
719 9c97e92f Serge Torres
    if pobyso_is_error_so_sa(funcSo):
720 9c97e92f Serge Torres
        pobyso_clear_obj(funcSo)
721 9c97e92f Serge Torres
        return None
722 3296902f Serge Torres
    #print "cpefa: function conversion OK."
723 9c97e92f Serge Torres
    ## Compute the Sollya version of the polynomial.
724 9c97e92f Serge Torres
    ## The conversion is made from a floating-point coefficients polynomial.
725 9c97e92f Serge Torres
    try:
726 9c97e92f Serge Torres
        polySa.base_ring().prec()
727 9c97e92f Serge Torres
        convFloatPolySa = polySa
728 9c97e92f Serge Torres
    except:
729 9c97e92f Serge Torres
        convFloatPolySa = realField[polySa.variables()[0]](polySa)
730 9c97e92f Serge Torres
    polySo = pobyso_float_poly_sa_so(convFloatPolySa)
731 9c97e92f Serge Torres
    if pobyso_is_error_so_sa(funcSo):
732 9c97e92f Serge Torres
        pobyso_clear_obj(funcSo)
733 9c97e92f Serge Torres
        pobyso_clear_obj(polySo)
734 9c97e92f Serge Torres
        return None
735 3296902f Serge Torres
    #print "cpefa: polynomial conversion to Sollya OK."
736 9c97e92f Serge Torres
    ## Copy both funcSo and polySo as they are needed later for the infnorm..
737 3296902f Serge Torres
    errorFuncSo = \
738 3296902f Serge Torres
        sollya_lib_build_function_sub(sollya_lib_copy_obj(funcSo), 
739 3296902f Serge Torres
                                      sollya_lib_copy_obj(polySo))
740 9c97e92f Serge Torres
    if pobyso_is_error_so_sa(errorFuncSo):
741 9c97e92f Serge Torres
        pobyso_clear_obj(errorFuncSo)
742 9c97e92f Serge Torres
        return None
743 3296902f Serge Torres
    #print "cpefa: error function in Sollya OK."
744 2669308a Serge Torres
    ## Evaluate the error function at both bounds, it may be usefull, if
745 2669308a Serge Torres
    #  the error function is monotonous
746 2669308a Serge Torres
    ## Lower bound stuff.
747 2669308a Serge Torres
    lowerBoundSo = pobyso_constant_sa_so(lowerBoundSa)
748 2669308a Serge Torres
    if pobyso_is_error_so_sa(lowerBoundSo):
749 2669308a Serge Torres
        pobyso_clear_obj(errorFuncSo)
750 2669308a Serge Torres
        pobyso_clear_obj(lowerBoundSo)
751 2669308a Serge Torres
        return None
752 2669308a Serge Torres
    errFuncAtLbSa = pobyso_evaluate_so_sa(errorFuncSo, lowerBoundSo)
753 2669308a Serge Torres
    pobyso_clear_obj(lowerBoundSo)
754 2669308a Serge Torres
    if errFuncAtLbSa is None:
755 2669308a Serge Torres
        pobyso_clear_obj(errorFuncSo)
756 2669308a Serge Torres
        return None
757 2669308a Serge Torres
    ## The result of the evaluation can be an interval.
758 2669308a Serge Torres
    try:
759 2669308a Serge Torres
        errFuncAtLbSa = errFuncAtLbSa.center()
760 2669308a Serge Torres
    except:
761 2669308a Serge Torres
        errFuncAtLbSa = errFuncAtLbSa
762 2669308a Serge Torres
    #print "cpefa: errFuncAtLbSa:", errFuncAtLbSa
763 2669308a Serge Torres
    ## Upper bound stuff.
764 2669308a Serge Torres
    upperBoundSo = pobyso_constant_sa_so(upperBoundSa)
765 2669308a Serge Torres
    if pobyso_is_error_so_sa(upperBoundSo):
766 2669308a Serge Torres
        pobyso_clear_obj(errorFuncSo)
767 2669308a Serge Torres
        pobyso_clear_obj(upperBoundSo)
768 2669308a Serge Torres
        return None
769 2669308a Serge Torres
    errFuncAtUbSa = pobyso_evaluate_so_sa(errorFuncSo, upperBoundSo)
770 2669308a Serge Torres
    pobyso_clear_obj(upperBoundSo)
771 2669308a Serge Torres
    if errFuncAtUbSa is None:
772 2669308a Serge Torres
        return None
773 2669308a Serge Torres
    ## The result of the evaluation can be an interval.
774 2669308a Serge Torres
    try:
775 2669308a Serge Torres
        errFuncAtUbSa = errFuncAtUbSa.center()
776 2669308a Serge Torres
    except:
777 2669308a Serge Torres
        errFuncAtUbSa = errFuncAtUbSa
778 2669308a Serge Torres
    #print "cpefa: errFuncAtUbSa:", errFuncAtUbSa
779 9c97e92f Serge Torres
    ## Compute the derivative.
780 9c97e92f Serge Torres
    diffErrorFuncSo = pobyso_diff_so_so(errorFuncSo)
781 9c97e92f Serge Torres
    pobyso_clear_obj(errorFuncSo)
782 9c97e92f Serge Torres
    if pobyso_is_error_so_sa(diffErrorFuncSo):
783 9c97e92f Serge Torres
        pobyso_clear_obj(diffErrorFuncSo)
784 9c97e92f Serge Torres
        return None
785 3296902f Serge Torres
        #print "cpefa: polynomial conversion to Sollya OK."
786 3296902f Serge Torres
    #print "cpefa: error function derivative in Sollya OK."
787 9c97e92f Serge Torres
    ## Compute the interval.
788 9c97e92f Serge Torres
    intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound)
789 9c97e92f Serge Torres
    if pobyso_is_error_so_sa(intervalSo):
790 9c97e92f Serge Torres
        pobyso_clear_obj(diffErrorFuncSo)
791 9c97e92f Serge Torres
        pobyso_clear_obj(intervalSo)
792 9c97e92f Serge Torres
        return None
793 9c97e92f Serge Torres
    ## Compute the infnorm of the error function.
794 9c97e92f Serge Torres
    errFuncSupNormSa = pobyso_supnorm_so_sa(polySo, 
795 9c97e92f Serge Torres
                                            funcSo, 
796 9c97e92f Serge Torres
                                            intervalSo, 
797 9c97e92f Serge Torres
                                            realFieldSa = realField)
798 9c97e92f Serge Torres
    pobyso_clear_obj(polySo)
799 9c97e92f Serge Torres
    pobyso_clear_obj(funcSo)
800 9c97e92f Serge Torres
    ## Compute the zeros of the derivative.
801 3296902f Serge Torres
    ### Give it a first try with dirtyfindzeros but it may
802 3296902f Serge Torres
    #   fail.
803 3296902f Serge Torres
    errorFuncMaxisSo = pobyso_dirty_find_zeros_so_so(diffErrorFuncSo, 
804 3296902f Serge Torres
                                                     intervalSo)
805 9c97e92f Serge Torres
    if pobyso_is_error_so_sa(errorFuncMaxisSo):
806 3296902f Serge Torres
        pobyso_clear_obj(diffErrorFuncSo)
807 3296902f Serge Torres
        pobyso_clear_obj(intervalSo)
808 9c97e92f Serge Torres
        pobyso_clear_obj(errorFuncMaxisSo)
809 9c97e92f Serge Torres
        return None
810 3296902f Serge Torres
    #print "cpefa: error function maxis in Sollya OK."
811 9c97e92f Serge Torres
    errorFuncMaxisSa = pobyso_float_list_so_sa(errorFuncMaxisSo)
812 9c97e92f Serge Torres
    pobyso_clear_obj(errorFuncMaxisSo)
813 3296902f Serge Torres
    #### If the list is empty try the more sophisticated
814 3296902f Serge Torres
    #    findzeros.
815 3296902f Serge Torres
    if len(errorFuncMaxisSa) == 0:
816 3296902f Serge Torres
        errorFuncMaxisSo = \
817 3296902f Serge Torres
            pobyso_find_zeros_so_so(diffErrorFuncSo, 
818 3296902f Serge Torres
                                    intervalSo)
819 3296902f Serge Torres
        if pobyso_is_error_so_sa(errorFuncMaxisSo):
820 3296902f Serge Torres
            pobyso_clear_obj(diffErrorFuncSo)
821 3296902f Serge Torres
            pobyso_clear_obj(intervalSo)
822 3296902f Serge Torres
            pobyso_clear_obj(errorFuncMaxisSo)
823 3296902f Serge Torres
            return None
824 3296902f Serge Torres
        #print "cpefa: error function maxis in Sollya OK."
825 3296902f Serge Torres
        #print "cpefa:", ; pobyso_autoprint(errorFuncMaxisSo)
826 3296902f Serge Torres
        ##### The findzeros functions returns intervals (ranges).
827 3296902f Serge Torres
        errorFuncRangeMaxisSa = pobyso_range_list_so_sa(errorFuncMaxisSo)
828 2669308a Serge Torres
        #print "cpefa:", errorFuncRangeMaxisSa
829 3296902f Serge Torres
        pobyso_clear_obj(errorFuncMaxisSo)
830 3296902f Serge Torres
        errorFuncMaxisSa = []
831 2669308a Serge Torres
        if len(errorFuncRangeMaxisSa) != 0:
832 2669308a Serge Torres
            for interval in errorFuncRangeMaxisSa:
833 2669308a Serge Torres
                errorFuncMaxisSa.append(interval.center())
834 2669308a Serge Torres
            #print "cpefa:", errorFuncMaxisSa
835 2669308a Serge Torres
        else: # The error function is monotonous. It reaches its maximum
836 2669308a Serge Torres
              # at either of the bounds.
837 2669308a Serge Torres
              errFuncMaxAtBounds = max(abs(errFuncAtLbSa), abs(errFuncAtUbSa))
838 2669308a Serge Torres
              if errFuncMaxAtBounds == abs(errFuncAtLbSa):
839 2669308a Serge Torres
                  errorFuncMaxisSa.append(lowerBoundSa)
840 2669308a Serge Torres
              else:
841 2669308a Serge Torres
                  errorFuncMaxisSa.append(upperBoundSa)
842 3296902f Serge Torres
    pobyso_clear_obj(diffErrorFuncSo)
843 3296902f Serge Torres
    pobyso_clear_obj(intervalSo)
844 9c97e92f Serge Torres
    ## If required, convert the numbers to rational numbers.
845 3296902f Serge Torres
    #print "cpefa - errorFuncMaxisSa:", errorFuncMaxisSa
846 9c97e92f Serge Torres
    if not contFracMaxErr is None:
847 9c97e92f Serge Torres
        for index in xrange(0, len(errorFuncMaxisSa)):
848 9c97e92f Serge Torres
            errorFuncMaxisSa[index] = \
849 9c97e92f Serge Torres
                errorFuncMaxisSa[index].nearby_rational(contFracMaxErr)
850 9c97e92f Serge Torres
    return (errorFuncMaxisSa, errFuncSupNormSa)
851 9c97e92f Serge Torres
# End cvp_polynomial_error_func_maxis
852 9c97e92f Serge Torres
#
853 9b0c03e7 Serge Torres
def cvp_polynomial_from_coeffs_and_exps(coeffsList, 
854 9b0c03e7 Serge Torres
                                        expsList, 
855 9b0c03e7 Serge Torres
                                        polyField = None,
856 9b0c03e7 Serge Torres
                                        theVar = None):
857 9b0c03e7 Serge Torres
    """
858 9b0c03e7 Serge Torres
    Build a polynomial in the classical monomials (possibly lacunary) basis 
859 9b0c03e7 Serge Torres
    from a list of coefficients and a list of exponents. The polynomial is in
860 9b0c03e7 Serge Torres
    the polynomial field given as argument.
861 9b0c03e7 Serge Torres
    """
862 9b0c03e7 Serge Torres
    if len(coeffsList) != len(expsList):
863 9b0c03e7 Serge Torres
        return None
864 9b0c03e7 Serge Torres
    ## If no variable is given, "x" is used.
865 9b0c03e7 Serge Torres
    ## If no polyField is given, we fall back on a polynomial field on RR.
866 9b0c03e7 Serge Torres
    if theVar is None:
867 9b0c03e7 Serge Torres
        if polyField is None:
868 9b0c03e7 Serge Torres
            theVar = x
869 9b0c03e7 Serge Torres
            polyField = RR[theVar]
870 9b0c03e7 Serge Torres
        else:
871 9b0c03e7 Serge Torres
            theVar = var(polyField.variable_name())
872 e2eb9ccc Serge Torres
    else: ### theVar is set.
873 e2eb9ccc Serge Torres
        ### No polyField, fallback on RR[theVar].
874 9b0c03e7 Serge Torres
        if polyField is None:
875 9b0c03e7 Serge Torres
            polyField = RR[theVar]
876 e2eb9ccc Serge Torres
        else: ### Both the polyFiled and theVar are set: create a new polyField
877 e2eb9ccc Serge Torres
              #   with theVar. The original polyField is not affected by the 
878 e2eb9ccc Serge Torres
              #   change.
879 9b0c03e7 Serge Torres
            polyField = polyField.change_var(theVar)  
880 9b0c03e7 Serge Torres
    ## Seed the polynomial.
881 9b0c03e7 Serge Torres
    poly = polyField(0)
882 9b0c03e7 Serge Torres
    ## Append the terms.
883 9b0c03e7 Serge Torres
    for coeff, exp in zip(coeffsList, expsList):
884 9b0c03e7 Serge Torres
        poly += polyField(coeff * theVar^exp)
885 9b0c03e7 Serge Torres
    return poly
886 9b0c03e7 Serge Torres
# End cvp_polynomial_from_coeffs_and_exps.
887 9b0c03e7 Serge Torres
#
888 9cf1fb38 Serge Torres
def cvp_remez_all_poly_error_func_maxis(funct, 
889 9b0c03e7 Serge Torres
                                        maxDegree, 
890 9b0c03e7 Serge Torres
                                        lowerBound, 
891 9b0c03e7 Serge Torres
                                        upperBound,
892 9b0c03e7 Serge Torres
                                        precsList, 
893 9b0c03e7 Serge Torres
                                        realField = None,
894 9b0c03e7 Serge Torres
                                        contFracMaxErr = None):
895 9b0c03e7 Serge Torres
    """
896 9b0c03e7 Serge Torres
    For a given function f, a degree and an interval, compute the 
897 9b0c03e7 Serge Torres
    maxima of the (f-remez_d(f)) function and those of the (f-truncRemez_d(f)) 
898 9b0c03e7 Serge Torres
    function over the interval.
899 9b0c03e7 Serge Torres
    """
900 9cf1fb38 Serge Torres
    ## If no realField argument is given try to retrieve it from the 
901 9cf1fb38 Serge Torres
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
902 9cf1fb38 Serge Torres
    if realField is None:
903 9cf1fb38 Serge Torres
        try:
904 9cf1fb38 Serge Torres
            ### Force failure if parent does not have prec() member.
905 9cf1fb38 Serge Torres
            lowerBound.parent().prec()
906 9cf1fb38 Serge Torres
            ### If no exception is thrown, set realField.
907 9cf1fb38 Serge Torres
            realField = lowerBound.parent()
908 9cf1fb38 Serge Torres
        except:
909 9cf1fb38 Serge Torres
            realField = RR
910 9cf1fb38 Serge Torres
    #print "Real field:", realField
911 9cf1fb38 Serge Torres
    funcSa         = func
912 9cf1fb38 Serge Torres
    funcAsStringSa = func._assume_str().replace("_SAGE_VAR_","",100)
913 9cf1fb38 Serge Torres
    print "Function as a string:", funcAsStringSa
914 9cf1fb38 Serge Torres
    ## Create the Sollya version of the function and compute the
915 9cf1fb38 Serge Torres
    #  Remez approximant
916 9cf1fb38 Serge Torres
    funcSo  = pobyso_parse_string(funcAsStringSa)
917 9cf1fb38 Serge Torres
    pStarSo = pobyso_remez_canonical_sa_so(funcAsStringSa, 
918 9cf1fb38 Serge Torres
                                           maxDegree, 
919 9cf1fb38 Serge Torres
                                           lowerBound,
920 9cf1fb38 Serge Torres
                                           upperBound)
921 9cf1fb38 Serge Torres
    ## Compute the error function and its derivative
922 9cf1fb38 Serge Torres
    ### First create the error function with copies since they are needed later.
923 9cf1fb38 Serge Torres
    errorFuncSo = sollya_lib_build_function_sub(sollya_lib_copy_obj(pStarSo), 
924 9cf1fb38 Serge Torres
                                                sollya_lib_copy_obj(funcSo))
925 9cf1fb38 Serge Torres
    intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound)
926 9cf1fb38 Serge Torres
    diffErrorFuncSo = pobyso_diff_so_so(errorFuncSo)
927 9cf1fb38 Serge Torres
    pobyso_clear_obj(errorFuncSo)
928 9cf1fb38 Serge Torres
    ## Compute the zeros of the derivative.
929 9c97e92f Serge Torres
    errorFuncMaxisSo = pobyso_dirty_find_zeros_so_so(diffErrorFuncSo, intervalSo)
930 9cf1fb38 Serge Torres
    pobyso_clear_obj(diffErrorFuncSo)
931 9c97e92f Serge Torres
    errorFuncMaxisSa = pobyso_float_list_so_sa(errorFuncMaxisSo)
932 9c97e92f Serge Torres
    pobyso_clear_obj(errorFuncMaxisSo)
933 9cf1fb38 Serge Torres
    ## Compute the truncated Remez polynomial and the error function.
934 9cf1fb38 Serge Torres
    truncFormatListSo = pobyso_build_list_of_ints_sa_so(*precsList)
935 9cf1fb38 Serge Torres
    pTruncSo = pobyso_round_coefficients_so_so(pStarSo, truncFormatListSo)
936 9cf1fb38 Serge Torres
    pobyso_clear_obj(pStarSo)
937 9cf1fb38 Serge Torres
    ### Compute the error function. This time we consume both the function
938 9cf1fb38 Serge Torres
    #   and the polynomial.
939 9cf1fb38 Serge Torres
    errorFuncSo = sollya_lib_build_function_sub(pTruncSo, funcSo)
940 9cf1fb38 Serge Torres
    ## Compute the derivative.
941 9cf1fb38 Serge Torres
    diffErrorFuncSo = pobyso_diff_so_so(errorFuncSo)
942 9cf1fb38 Serge Torres
    pobyso_clear_obj(errorFuncSo)
943 9cf1fb38 Serge Torres
    ## Compute the zeros of the derivative.
944 9c97e92f Serge Torres
    errorFuncMaxisSo = pobyso_dirty_find_zeros_so_so(diffErrorFuncSo, intervalSo)
945 9cf1fb38 Serge Torres
    pobyso_clear_obj(diffErrorFuncSo)
946 9cf1fb38 Serge Torres
    pobyso_clear_obj(intervalSo)
947 9c97e92f Serge Torres
    errorFuncTruncMaxisSa = pobyso_float_list_so_sa(errorFuncMaxisSo)
948 9c97e92f Serge Torres
    pobyso_clear_obj(errorFuncMaxisSo)
949 9c97e92f Serge Torres
    ## Merge with the first list, removing duplicates if any.
950 9c97e92f Serge Torres
    errorFuncMaxisSa.extend(elem for elem in errorFuncTruncMaxisSa \
951 9c97e92f Serge Torres
                            if elem not in errorFuncMaxisSa)
952 9c97e92f Serge Torres
    errorFuncMaxisSa.sort()
953 9cf1fb38 Serge Torres
    ## If required, convert the numbers to rational numbers.
954 9cf1fb38 Serge Torres
    if not contFracMaxErr is None:
955 9c97e92f Serge Torres
        for index in xrange(0, len(errorFuncMaxisSa)):
956 9c97e92f Serge Torres
            errorFuncMaxisSa[index] = \
957 9c97e92f Serge Torres
                errorFuncMaxisSa[index].nearby_rational(contFracMaxErr)
958 9c97e92f Serge Torres
    return errorFuncMaxisSa
959 9cf1fb38 Serge Torres
# End cvp_remez_all_poly_error_func_maxis.
960 9b0c03e7 Serge Torres
#
961 724064f1 Serge Torres
def cvp_remez_all_poly_error_func_zeros(funct, 
962 724064f1 Serge Torres
                                        maxDegree, 
963 724064f1 Serge Torres
                                        lowerBound, 
964 724064f1 Serge Torres
                                        upperBound,
965 724064f1 Serge Torres
                                        precsList, 
966 04d64614 Serge Torres
                                        realField = None,
967 04d64614 Serge Torres
                                        contFracMaxErr = None):
968 724064f1 Serge Torres
    """
969 724064f1 Serge Torres
    For a given function f, a degree and an interval, compute the 
970 04d64614 Serge Torres
    zeros of the (f-remez_d(f)) function and those of the (f-truncRemez_d(f)) 
971 9cf1fb38 Serge Torres
    function over the interval.
972 724064f1 Serge Torres
    """
973 04d64614 Serge Torres
    ## If no realField argument is given try to retrieve it from the 
974 04d64614 Serge Torres
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
975 04d64614 Serge Torres
    if realField is None:
976 04d64614 Serge Torres
        try:
977 04d64614 Serge Torres
            ### Force failure if parent does not have prec() member.
978 04d64614 Serge Torres
            lowerBound.parent().prec()
979 04d64614 Serge Torres
            ### If no exception is thrown, set realField.
980 04d64614 Serge Torres
            realField = lowerBound.parent()
981 04d64614 Serge Torres
        except:
982 04d64614 Serge Torres
            realField = RR
983 04d64614 Serge Torres
    #print "Real field:", realField
984 724064f1 Serge Torres
    funcSa         = func
985 724064f1 Serge Torres
    funcAsStringSa = func._assume_str().replace("_SAGE_VAR_","",100)
986 724064f1 Serge Torres
    print "Function as a string:", funcAsStringSa
987 724064f1 Serge Torres
    ## Create the Sollya version of the function and compute the
988 724064f1 Serge Torres
    #  Remez approximant
989 724064f1 Serge Torres
    funcSo  = pobyso_parse_string(funcAsStringSa)
990 724064f1 Serge Torres
    pStarSo = pobyso_remez_canonical_sa_so(funcAsStringSa, 
991 724064f1 Serge Torres
                                           maxDegree, 
992 724064f1 Serge Torres
                                           lowerBound,
993 724064f1 Serge Torres
                                           upperBound)
994 724064f1 Serge Torres
    ## Compute the zeroes of the error function.
995 724064f1 Serge Torres
    ### First create the error function with copies since they are needed later.
996 724064f1 Serge Torres
    errorFuncSo = sollya_lib_build_function_sub(sollya_lib_copy_obj(pStarSo), 
997 724064f1 Serge Torres
                                                sollya_lib_copy_obj(funcSo))
998 04d64614 Serge Torres
    intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound)
999 724064f1 Serge Torres
    errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(errorFuncSo, intervalSo)
1000 724064f1 Serge Torres
    pobyso_clear_obj(errorFuncSo) # Clears funcSo and pStarSo as well.
1001 724064f1 Serge Torres
    #print "Zeroes of the error function from Sollya:"
1002 724064f1 Serge Torres
    #pobyso_autoprint(errorFuncZerosSo)
1003 724064f1 Serge Torres
    errorFuncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo)
1004 724064f1 Serge Torres
    pobyso_clear_obj(errorFuncZerosSo)
1005 724064f1 Serge Torres
    #print "\nZeroes of the error function from Sage:"
1006 724064f1 Serge Torres
    #print errorFuncZerosSa
1007 724064f1 Serge Torres
    #
1008 724064f1 Serge Torres
    ## Deal with the truncated polynomial now.
1009 724064f1 Serge Torres
    ### Create the formats list. Notice the "*" before the list variable name.
1010 724064f1 Serge Torres
    truncFormatListSo = pobyso_build_list_of_ints_sa_so(*precsList)
1011 9b0c03e7 Serge Torres
    #print "Precisions list as Sollya object:", 
1012 9cf1fb38 Serge Torres
    #pobyso_autoprint(truncFormatListSo)
1013 724064f1 Serge Torres
    pTruncSo = pobyso_round_coefficients_so_so(pStarSo, truncFormatListSo)
1014 9b0c03e7 Serge Torres
    #print "Truncated polynomial:", ; pobyso_autoprint(pTruncSo)
1015 724064f1 Serge Torres
    ### Compute the error function. This time we consume both the function
1016 724064f1 Serge Torres
    #   and the polynomial.
1017 724064f1 Serge Torres
    errorFuncSo = sollya_lib_build_function_sub(pTruncSo, 
1018 724064f1 Serge Torres
                                                funcSo)
1019 724064f1 Serge Torres
    errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(errorFuncSo, intervalSo)
1020 724064f1 Serge Torres
    pobyso_clear_obj(pStarSo)
1021 9b0c03e7 Serge Torres
    #print "Zeroes of the error function for the truncated polynomial from Sollya:"
1022 9cf1fb38 Serge Torres
    #pobyso_autoprint(errorFuncZerosSo)
1023 724064f1 Serge Torres
    errorFuncTruncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo)
1024 724064f1 Serge Torres
    pobyso_clear_obj(errorFuncZerosSo)
1025 724064f1 Serge Torres
    ## Sollya objects clean up.
1026 724064f1 Serge Torres
    pobyso_clear_obj(intervalSo)
1027 724064f1 Serge Torres
    errorFuncZerosSa += errorFuncTruncZerosSa
1028 724064f1 Serge Torres
    errorFuncZerosSa.sort()
1029 04d64614 Serge Torres
    ## If required, convert the numbers to rational numbers.
1030 04d64614 Serge Torres
    if not contFracMaxErr is None:
1031 04d64614 Serge Torres
        for index in xrange(0, len(errorFuncZerosSa)):
1032 04d64614 Serge Torres
            errorFuncZerosSa[index] = \
1033 04d64614 Serge Torres
                errorFuncZerosSa[index].nearby_rational(contFracMaxErr)
1034 04d64614 Serge Torres
    return errorFuncZerosSa
1035 04d64614 Serge Torres
    #
1036 04d64614 Serge Torres
# End remez_all_poly_error_func_zeros
1037 04d64614 Serge Torres
#
1038 04d64614 Serge Torres
def cvp_remez_poly_error_func_zeros(funct, 
1039 04d64614 Serge Torres
                                    maxDegree, 
1040 04d64614 Serge Torres
                                    lowerBound, 
1041 04d64614 Serge Torres
                                    upperBound,
1042 04d64614 Serge Torres
                                    realField = None,
1043 04d64614 Serge Torres
                                    contFracMaxErr = None):
1044 04d64614 Serge Torres
    """
1045 04d64614 Serge Torres
    For a given function f, a degree and an interval, compute the 
1046 04d64614 Serge Torres
    zeros of the (f-remez_d(f)) function.
1047 04d64614 Serge Torres
    """
1048 04d64614 Serge Torres
    ## If no realField argument is given try to retrieve it from the 
1049 04d64614 Serge Torres
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
1050 04d64614 Serge Torres
    if realField is None:
1051 04d64614 Serge Torres
        try:
1052 04d64614 Serge Torres
            ### Force failure if parent does not have prec() member.
1053 04d64614 Serge Torres
            lowerBound.parent().prec()
1054 04d64614 Serge Torres
            ### If no exception is thrown, set realField.
1055 04d64614 Serge Torres
            realField = lowerBound.parent()
1056 04d64614 Serge Torres
        except:
1057 04d64614 Serge Torres
            realField = RR
1058 04d64614 Serge Torres
    #print "Real field:", realField
1059 04d64614 Serge Torres
    funcSa         = func
1060 04d64614 Serge Torres
    funcAsStringSa = func._assume_str().replace("_SAGE_VAR_","",100)
1061 04d64614 Serge Torres
    #print "Function as a string:", funcAsStringSa
1062 04d64614 Serge Torres
    ## Create the Sollya version of the function and compute the
1063 04d64614 Serge Torres
    #  Remez approximant
1064 04d64614 Serge Torres
    funcSo  = pobyso_parse_string(funcAsStringSa)
1065 04d64614 Serge Torres
    pStarSo = pobyso_remez_canonical_sa_so(funcAsStringSa, 
1066 04d64614 Serge Torres
                                           maxDegree, 
1067 04d64614 Serge Torres
                                           lowerBound,
1068 04d64614 Serge Torres
                                           upperBound)
1069 04d64614 Serge Torres
    ## Compute the zeroes of the error function.
1070 04d64614 Serge Torres
    ### Error function creation consumes both pStarSo and funcSo.
1071 04d64614 Serge Torres
    errorFuncSo = sollya_lib_build_function_sub(pStarSo, funcSo)
1072 04d64614 Serge Torres
    intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound)
1073 04d64614 Serge Torres
    errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(errorFuncSo, intervalSo)
1074 04d64614 Serge Torres
    pobyso_clear_obj(errorFuncSo) # Clears funcSo and pStarSo as well.
1075 04d64614 Serge Torres
    #print "Zeroes of the error function from Sollya:"
1076 04d64614 Serge Torres
    #pobyso_autoprint(errorFuncZerosSo)
1077 04d64614 Serge Torres
    errorFuncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo)
1078 04d64614 Serge Torres
    pobyso_clear_obj(errorFuncZerosSo)
1079 04d64614 Serge Torres
    ## Sollya objects clean up.
1080 04d64614 Serge Torres
    pobyso_clear_obj(intervalSo)
1081 04d64614 Serge Torres
    ## Converting to rational numbers, if required.
1082 04d64614 Serge Torres
    if not contFracMaxErr is None:
1083 04d64614 Serge Torres
        for index in xrange(0, len(errorFuncZerosSa)):
1084 04d64614 Serge Torres
            errorFuncZerosSa[index] = \
1085 04d64614 Serge Torres
                errorFuncZerosSa[index].nearby_rational(contFracMaxErr)
1086 724064f1 Serge Torres
    return errorFuncZerosSa
1087 724064f1 Serge Torres
    #
1088 724064f1 Serge Torres
# End remez_poly_error_func_zeros
1089 724064f1 Serge Torres
#
1090 62861417 Serge Torres
def cvp_round_to_bits(num, numBits):
1091 62861417 Serge Torres
    """
1092 62861417 Serge Torres
    Round "num" to "numBits" bits.
1093 62861417 Serge Torres
    @param num    : the number to round;
1094 62861417 Serge Torres
    @param numBits: the number of bits to round to.
1095 62861417 Serge Torres
    """
1096 62861417 Serge Torres
    if num == 0:
1097 62861417 Serge Torres
        return num
1098 62861417 Serge Torres
    log2ofNum  = 0
1099 62861417 Serge Torres
    numRounded = 0
1100 62861417 Serge Torres
    ## Avoid conversion to floating-point if not necessary.
1101 62861417 Serge Torres
    try:
1102 62861417 Serge Torres
        log2OfNum = num.abs().log2()
1103 62861417 Serge Torres
    except:
1104 62861417 Serge Torres
        log2OfNum = RR(num).abs().log2()
1105 62861417 Serge Torres
    ## Works equally well for num >= 1 and num < 1.
1106 62861417 Serge Torres
    log2OfNum = ceil(log2OfNum)
1107 62861417 Serge Torres
    # print "cvp_round_to_bits - Log2OfNum:", log2OfNum
1108 62861417 Serge Torres
    divMult = log2OfNum - numBits
1109 62861417 Serge Torres
    #print "cvp_round_to_bits - DivMult:", divMult
1110 62861417 Serge Torres
    if divMult != 0:
1111 62861417 Serge Torres
        numRounded = round(num/2^divMult) * 2^divMult
1112 62861417 Serge Torres
    else:
1113 62861417 Serge Torres
        numRounded = num
1114 62861417 Serge Torres
    return numRounded
1115 62861417 Serge Torres
# End cvp_round_to_bits
1116 62861417 Serge Torres
#
1117 9645ea29 Serge Torres
def cvp_vector_in_basis(vect, basis):
1118 9645ea29 Serge Torres
    """
1119 9645ea29 Serge Torres
    Compute the coordinates of "vect" in "basis" by
1120 9645ea29 Serge Torres
    solving a linear system.
1121 9cf1fb38 Serge Torres
    @param vect  the vector we want to compute the coordinates of
1122 9645ea29 Serge Torres
                  in coordinates of the ambient space;
1123 9cf1fb38 Serge Torres
    @param basis the basis we want to compute the coordinates in
1124 9645ea29 Serge Torres
                  as a matrix relative to the ambient space.
1125 9645ea29 Serge Torres
    """
1126 9645ea29 Serge Torres
    ## Create the variables for the linear equations.
1127 9645ea29 Serge Torres
    varDeclString = ""
1128 9645ea29 Serge Torres
    basisIterationsRange = xrange(0, basis.nrows())
1129 9645ea29 Serge Torres
    ### Building variables declaration string.
1130 9645ea29 Serge Torres
    for index in basisIterationsRange:
1131 9645ea29 Serge Torres
        varName = "a" + str(index)
1132 9645ea29 Serge Torres
        if varDeclString == "":
1133 9645ea29 Serge Torres
            varDeclString += varName
1134 9645ea29 Serge Torres
        else:
1135 9645ea29 Serge Torres
            varDeclString += "," + varName
1136 9645ea29 Serge Torres
    ### Variables declaration
1137 9645ea29 Serge Torres
    varsList = var(varDeclString)
1138 9645ea29 Serge Torres
    sage_eval("var('" + varDeclString + "')")
1139 9645ea29 Serge Torres
    ## Create the equations
1140 9645ea29 Serge Torres
    equationString = ""
1141 9645ea29 Serge Torres
    equationsList = []
1142 9645ea29 Serge Torres
    for vIndex in xrange(0, len(vect)):
1143 9645ea29 Serge Torres
        equationString = ""
1144 9645ea29 Serge Torres
        for bIndex in basisIterationsRange:
1145 9645ea29 Serge Torres
            if equationString != "":
1146 9645ea29 Serge Torres
                equationString += "+"
1147 9645ea29 Serge Torres
            equationString += str(varsList[bIndex]) + "*" + str(basis[bIndex,vIndex])
1148 9645ea29 Serge Torres
        equationString += " == " + str(vect[vIndex])
1149 9645ea29 Serge Torres
        equationsList.append(sage_eval(equationString))
1150 9cf1fb38 Serge Torres
    ## Solve the equations system. The solution dictionary is needed
1151 9645ea29 Serge Torres
    #  to recover the values of the solutions.
1152 9645ea29 Serge Torres
    solutions = solve(equationsList,varsList, solution_dict=True)
1153 9cf1fb38 Serge Torres
    ## This code is deactivated: did not solve the problem.
1154 9cf1fb38 Serge Torres
    """
1155 9cf1fb38 Serge Torres
    if len(solutions) == 0:
1156 9cf1fb38 Serge Torres
        print "Trying Maxima to_poly_sove."
1157 9cf1fb38 Serge Torres
        solutions = solve(equationsList,varsList, solution_dict=True, to_poly_solve = 'force')
1158 9cf1fb38 Serge Torres
    """
1159 9645ea29 Serge Torres
    #print "Solutions:", s
1160 9645ea29 Serge Torres
    ## Recover solutions in rational components vector.
1161 9645ea29 Serge Torres
    vectInBasis = vector(QQ, basis.nrows())
1162 9645ea29 Serge Torres
    ### There can be several solution, in the general case.
1163 9cf1fb38 Serge Torres
    #   Here, there is only one (or none). For each solution, each 
1164 9645ea29 Serge Torres
    #   variable has to be searched for.
1165 9645ea29 Serge Torres
    for sol in solutions:
1166 9645ea29 Serge Torres
        for bIndex in basisIterationsRange:
1167 9645ea29 Serge Torres
            vectInBasis[bIndex] = sol[varsList[bIndex]]
1168 9645ea29 Serge Torres
    return vectInBasis
1169 9645ea29 Serge Torres
# End cpv_vector_in_basis.
1170 9645ea29 Serge Torres
#
1171 94c8237b Serge Torres
sys.stderr.write("... functions for CVP loaded.\n")