Statistiques
| Branche: | Révision :

cvp / src / functions_for_cvp.sage @ 4a0c5e95

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