Statistiques
| Branche: | Révision :

cvp / src / functions_for_cvp.sage @ c7bf1784

Historique | Voir | Annoter | Télécharger (43,32 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 9645ea29 Serge Torres
def cvp_float_basis(monomialsList, pointsList, realField):
525 9645ea29 Serge Torres
    """
526 9645ea29 Serge Torres
    For a given monomials list and points list, compute the floating-point
527 9645ea29 Serge Torres
    basis matrix.
528 9645ea29 Serge Torres
    """
529 9645ea29 Serge Torres
    numRows    = len(monomialsList)
530 9645ea29 Serge Torres
    numCols    = len(pointsList)
531 9645ea29 Serge Torres
    if numRows == 0 or numCols == 0:
532 9645ea29 Serge Torres
        return matrix(realField, 0, 0)
533 9645ea29 Serge Torres
    #
534 9645ea29 Serge Torres
    floatBasis = matrix(realField, numRows, numCols)
535 9645ea29 Serge Torres
    for rIndex in xrange(0, numRows):
536 9645ea29 Serge Torres
        for cIndex in xrange(0, numCols):
537 9645ea29 Serge Torres
            floatBasis[rIndex,cIndex] = \
538 9645ea29 Serge Torres
                monomialsList[rIndex](realField(pointsList[cIndex]))
539 9645ea29 Serge Torres
    return floatBasis
540 9645ea29 Serge Torres
# End cvp_float_basis
541 9645ea29 Serge Torres
#
542 9645ea29 Serge Torres
def cvp_float_vector_for_approx(func, 
543 9645ea29 Serge Torres
                                basisPointsList,
544 9645ea29 Serge Torres
                                realField):
545 9645ea29 Serge Torres
    """
546 9645ea29 Serge Torres
    Compute a floating-point vector for the function and the points list.
547 9645ea29 Serge Torres
    """
548 9645ea29 Serge Torres
    #
549 9645ea29 Serge Torres
    ## Some local variables.
550 9645ea29 Serge Torres
    basisPointsNum = len(basisPointsList)
551 9645ea29 Serge Torres
    #
552 9645ea29 Serge Torres
    ##
553 9645ea29 Serge Torres
    vVect = vector(realField, basisPointsNum)
554 9645ea29 Serge Torres
    for vIndex in xrange(0,basisPointsNum):
555 9645ea29 Serge Torres
        vVect[vIndex] = \
556 9645ea29 Serge Torres
            func(basisPointsList[vIndex])
557 9645ea29 Serge Torres
    return vVect
558 9645ea29 Serge Torres
# End cvp_float_vector_for_approx.
559 9645ea29 Serge Torres
#
560 e2eb9ccc Serge Torres
def cvp_func_abs_max_for_points(func, pointsList):
561 e2eb9ccc Serge Torres
    """
562 e2eb9ccc Serge Torres
    Compute the maximum absolute value of a function for a list of 
563 e2eb9ccc Serge Torres
    points.
564 e2eb9ccc Serge Torres
    If several points yield the same value and this value is the maximum,
565 e2eb9ccc Serge Torres
    an unspecified point of this set is returned.
566 e2eb9ccc Serge Torres
    @return (theMaxPoint, theMaxValue) 
567 e2eb9ccc Serge Torres
    """
568 e2eb9ccc Serge Torres
    evalDict = dict()
569 e2eb9ccc Serge Torres
    if len(pointsList) == 0:
570 e2eb9ccc Serge Torres
        return None
571 e2eb9ccc Serge Torres
    #
572 e2eb9ccc Serge Torres
    for pt in pointsList:
573 e2eb9ccc Serge Torres
        evalDict[abs(func(pt))] = pt
574 e2eb9ccc Serge Torres
    maxAbs = max(evalDict.keys())
575 e2eb9ccc Serge Torres
    return (evalDict[maxAbs], maxAbs)
576 e2eb9ccc Serge Torres
# End cvp_func_abs_max_for_points
577 e2eb9ccc Serge Torres
#
578 9645ea29 Serge Torres
def cvp_hkz_reduce(intBasis):
579 9645ea29 Serge Torres
    """
580 9645ea29 Serge Torres
    Thin and simplistic wrapper the HKZ function of the FP_LLL module.
581 9645ea29 Serge Torres
    """
582 9645ea29 Serge Torres
    fplllIntBasis = FP_LLL(intBasis)
583 9645ea29 Serge Torres
    fplllIntBasis.HKZ()
584 9645ea29 Serge Torres
    return fplllIntBasis._sage_()
585 9645ea29 Serge Torres
# End cvp_hkz_reduce.
586 9645ea29 Serge Torres
#
587 62861417 Serge Torres
def cvp_int_basis(floatBasis, 
588 62861417 Serge Torres
                  commonScalingExp, 
589 62861417 Serge Torres
                  extraScalingExpsList):
590 9645ea29 Serge Torres
    """
591 62861417 Serge Torres
    From the float basis, the common scaling factor and the extra exponents 
592 62861417 Serge Torres
    compute the integral basis.
593 9645ea29 Serge Torres
    """
594 62861417 Serge Torres
    ## Checking arguments.
595 62861417 Serge Torres
    if floatBasis.nrows() != len(extraScalingExpsList):
596 62861417 Serge Torres
        return None
597 9645ea29 Serge Torres
    intBasis = matrix(ZZ, floatBasis.nrows(), floatBasis.ncols())
598 9645ea29 Serge Torres
    for rIndex in xrange(0, floatBasis.nrows()):
599 9645ea29 Serge Torres
        for cIndex in xrange(0, floatBasis.ncols()):
600 9645ea29 Serge Torres
            intBasis[rIndex, cIndex] = \
601 9b0c03e7 Serge Torres
            (floatBasis[rIndex, cIndex] * \
602 9b0c03e7 Serge Torres
            2^(commonScalingExp + extraScalingExpsList[rIndex])).round()
603 9645ea29 Serge Torres
    return intBasis
604 9645ea29 Serge Torres
# End cvp_int_basis.
605 9645ea29 Serge Torres
#
606 62861417 Serge Torres
def cvp_int_vector_for_approx(floatVect, commonScalingExp, extraScalingExp):
607 9b0c03e7 Serge Torres
    """
608 9b0c03e7 Serge Torres
    Compute the integral version of the function vector.
609 9b0c03e7 Serge Torres
    """
610 62861417 Serge Torres
    totalScalingFactor = 2^(commonScalingExp + extraScalingExp)
611 9645ea29 Serge Torres
    intVect = vector(ZZ, len(floatVect))
612 9645ea29 Serge Torres
    for index in xrange(0, len(floatVect)):
613 9645ea29 Serge Torres
        intVect[index] = (floatVect[index] * totalScalingFactor).round()
614 9645ea29 Serge Torres
    return intVect
615 9645ea29 Serge Torres
# End cvp_int_vector_for_approx.
616 9645ea29 Serge Torres
#
617 9645ea29 Serge Torres
def cvp_lll_reduce(intBasis):
618 9645ea29 Serge Torres
    """
619 9645ea29 Serge Torres
    Thin and simplistic wrapper around the LLL function
620 9645ea29 Serge Torres
    """
621 9645ea29 Serge Torres
    return intBasis.LLL()
622 9645ea29 Serge Torres
# End cvp_lll_reduce.
623 9645ea29 Serge Torres
#
624 9645ea29 Serge Torres
def cvp_monomials_list(exponentsList, varName = None):
625 9645ea29 Serge Torres
    """
626 9645ea29 Serge Torres
    Create a list of monomials corresponding to the given exponentsList.
627 9645ea29 Serge Torres
    Monomials are defined as functions.
628 9645ea29 Serge Torres
    """
629 9645ea29 Serge Torres
    monomialsList = []
630 9645ea29 Serge Torres
    for exponent in exponentsList:
631 9645ea29 Serge Torres
        if varName is None:
632 9645ea29 Serge Torres
            monomialsList.append((x^exponent).function(x))
633 9645ea29 Serge Torres
        else:
634 9645ea29 Serge Torres
            monomialsList.append((varName^exponent).function(varName))
635 9645ea29 Serge Torres
    return monomialsList
636 9645ea29 Serge Torres
# End cvp_monomials_list.
637 9645ea29 Serge Torres
#
638 62861417 Serge Torres
def cvp_polynomial_coeffs_from_vect(cvpVectInBasis,
639 9cf1fb38 Serge Torres
                                    coeffsPrecList, 
640 9cf1fb38 Serge Torres
                                    minCoeffsExpList,
641 9cf1fb38 Serge Torres
                                    extraFuncScalingExp):
642 9cf1fb38 Serge Torres
    """
643 9cf1fb38 Serge Torres
    Computes polynomial coefficients out of the elements of the CVP vector.
644 9cf1fb38 Serge Torres
    @todo
645 9cf1fb38 Serge Torres
    Rewrite the code with a single exponentiation, at the very end.
646 9cf1fb38 Serge Torres
    """
647 62861417 Serge Torres
    numElements = len(cvpVectInBasis)
648 62861417 Serge Torres
    ## Arguments check.
649 62861417 Serge Torres
    if numElements != len(minCoeffsExpList) or \
650 62861417 Serge Torres
       numElements != len(coeffsPrecList):
651 62861417 Serge Torres
        return None
652 62861417 Serge Torres
    polynomialCoeffsList = []
653 62861417 Serge Torres
    for index in xrange(0, numElements):
654 62861417 Serge Torres
        currentCoeff = cvp_round_to_bits(cvpVectInBasis[index],
655 62861417 Serge Torres
                                         coeffsPrecList[index])
656 e2eb9ccc Serge Torres
        #print "cvp_polynomial_coeffs - current coefficient rounded:", currentCoeff
657 62861417 Serge Torres
        currentCoeff *= 2^(minCoeffsExpList[index])
658 e2eb9ccc Serge Torres
        #print "cvp_polynomial_coeffs - current coefficient scaled :", currentCoeff
659 62861417 Serge Torres
        currentCoeff *= 2^(-coeffsPrecList[index])
660 e2eb9ccc Serge Torres
        #print "cvp_polynomial_coeffs - current coefficient prec corrected :", currentCoeff
661 62861417 Serge Torres
        currentCoeff *= 2^(-extraFuncScalingExp)
662 e2eb9ccc Serge Torres
        #print "cvp_polynomial_coeffs - current coefficient extra func scaled :", currentCoeff
663 62861417 Serge Torres
        polynomialCoeffsList.append(currentCoeff)
664 62861417 Serge Torres
    return polynomialCoeffsList
665 62861417 Serge Torres
# En polynomial_coeffs_from_vect.
666 62861417 Serge Torres
#
667 9c97e92f Serge Torres
def cvp_polynomial_error_func_maxis(funcSa,
668 9c97e92f Serge Torres
                                    polySa, 
669 9c97e92f Serge Torres
                                    lowerBoundSa, 
670 9c97e92f Serge Torres
                                    upperBoundSa,
671 9c97e92f Serge Torres
                                    realField = None,
672 9c97e92f Serge Torres
                                    contFracMaxErr = None):
673 9c97e92f Serge Torres
    """
674 9c97e92f Serge Torres
    For a given function, approximation polynomial and interval (given 
675 9c97e92f Serge Torres
    as bounds) compute the maxima of the functSa - polySo on the interval.
676 9c97e92f Serge Torres
    Also computes the infnorm of the error function.
677 9c97e92f Serge Torres
    """
678 9c97e92f Serge Torres
    ## Arguments check.
679 9c97e92f Serge Torres
    # @todo.
680 9c97e92f Serge Torres
    ## If no realField argument is given try to retrieve it from the 
681 9c97e92f Serge Torres
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
682 9c97e92f Serge Torres
    if realField is None:
683 9c97e92f Serge Torres
        try:
684 9c97e92f Serge Torres
            ### Force failure if parent does not have prec() member.
685 9c97e92f Serge Torres
            lowerBound.parent().prec()
686 9c97e92f Serge Torres
            ### If no exception is thrown, set realField.
687 9c97e92f Serge Torres
            realField = lowerBound.parent()
688 9c97e92f Serge Torres
        except:
689 9c97e92f Serge Torres
            realField = RR
690 9c97e92f Serge Torres
    #print "Real field:", realField
691 9c97e92f Serge Torres
    ## Compute the Sollya version of the function.
692 9c97e92f Serge Torres
    funcAsStringSa = funcSa._assume_str().replace("_SAGE_VAR_","",100)
693 9c97e92f Serge Torres
    funcSo  = pobyso_parse_string(funcAsStringSa)
694 9c97e92f Serge Torres
    if pobyso_is_error_so_sa(funcSo):
695 9c97e92f Serge Torres
        pobyso_clear_obj(funcSo)
696 9c97e92f Serge Torres
        return None
697 9c97e92f Serge Torres
    ## Compute the Sollya version of the polynomial.
698 9c97e92f Serge Torres
    ## The conversion is made from a floating-point coefficients polynomial.
699 9c97e92f Serge Torres
    try:
700 9c97e92f Serge Torres
        polySa.base_ring().prec()
701 9c97e92f Serge Torres
        convFloatPolySa = polySa
702 9c97e92f Serge Torres
    except:
703 9c97e92f Serge Torres
        convFloatPolySa = realField[polySa.variables()[0]](polySa)
704 9c97e92f Serge Torres
    polySo = pobyso_float_poly_sa_so(convFloatPolySa)
705 9c97e92f Serge Torres
    if pobyso_is_error_so_sa(funcSo):
706 9c97e92f Serge Torres
        pobyso_clear_obj(funcSo)
707 9c97e92f Serge Torres
        pobyso_clear_obj(polySo)
708 9c97e92f Serge Torres
        return None
709 9c97e92f Serge Torres
    ## Copy both funcSo and polySo as they are needed later for the infnorm..
710 9c97e92f Serge Torres
    errorFuncSo = sollya_lib_build_function_sub(sollya_lib_copy_obj(funcSo), 
711 9c97e92f Serge Torres
                                                sollya_lib_copy_obj(polySo))
712 9c97e92f Serge Torres
    if pobyso_is_error_so_sa(errorFuncSo):
713 9c97e92f Serge Torres
        pobyso_clear_obj(errorFuncSo)
714 9c97e92f Serge Torres
        return None
715 9c97e92f Serge Torres
    ## Compute the derivative.
716 9c97e92f Serge Torres
    diffErrorFuncSo = pobyso_diff_so_so(errorFuncSo)
717 9c97e92f Serge Torres
    pobyso_clear_obj(errorFuncSo)
718 9c97e92f Serge Torres
    if pobyso_is_error_so_sa(diffErrorFuncSo):
719 9c97e92f Serge Torres
        pobyso_clear_obj(diffErrorFuncSo)
720 9c97e92f Serge Torres
        return None
721 9c97e92f Serge Torres
    ## Compute the interval.
722 9c97e92f Serge Torres
    intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound)
723 9c97e92f Serge Torres
    if pobyso_is_error_so_sa(intervalSo):
724 9c97e92f Serge Torres
        pobyso_clear_obj(diffErrorFuncSo)
725 9c97e92f Serge Torres
        pobyso_clear_obj(intervalSo)
726 9c97e92f Serge Torres
        return None
727 9c97e92f Serge Torres
    ## Compute the infnorm of the error function.
728 9c97e92f Serge Torres
    errFuncSupNormSa = pobyso_supnorm_so_sa(polySo, 
729 9c97e92f Serge Torres
                                            funcSo, 
730 9c97e92f Serge Torres
                                            intervalSo, 
731 9c97e92f Serge Torres
                                            realFieldSa = realField)
732 9c97e92f Serge Torres
    pobyso_clear_obj(polySo)
733 9c97e92f Serge Torres
    pobyso_clear_obj(funcSo)
734 9c97e92f Serge Torres
    ## Compute the zeros of the derivative.
735 9c97e92f Serge Torres
    errorFuncMaxisSo = pobyso_dirty_find_zeros_so_so(diffErrorFuncSo, intervalSo)
736 9c97e92f Serge Torres
    pobyso_clear_obj(diffErrorFuncSo)
737 9c97e92f Serge Torres
    pobyso_clear_obj(intervalSo)
738 9c97e92f Serge Torres
    if pobyso_is_error_so_sa(errorFuncMaxisSo):
739 9c97e92f Serge Torres
        pobyso_clear_obj(errorFuncMaxisSo)
740 9c97e92f Serge Torres
        return None
741 9c97e92f Serge Torres
    errorFuncMaxisSa = pobyso_float_list_so_sa(errorFuncMaxisSo)
742 9c97e92f Serge Torres
    pobyso_clear_obj(errorFuncMaxisSo)
743 9c97e92f Serge Torres
    ## If required, convert the numbers to rational numbers.
744 9c97e92f Serge Torres
    if not contFracMaxErr is None:
745 9c97e92f Serge Torres
        for index in xrange(0, len(errorFuncMaxisSa)):
746 9c97e92f Serge Torres
            errorFuncMaxisSa[index] = \
747 9c97e92f Serge Torres
                errorFuncMaxisSa[index].nearby_rational(contFracMaxErr)
748 9c97e92f Serge Torres
    return (errorFuncMaxisSa, errFuncSupNormSa)
749 9c97e92f Serge Torres
# End cvp_polynomial_error_func_maxis
750 9c97e92f Serge Torres
#
751 9b0c03e7 Serge Torres
def cvp_polynomial_from_coeffs_and_exps(coeffsList, 
752 9b0c03e7 Serge Torres
                                        expsList, 
753 9b0c03e7 Serge Torres
                                        polyField = None,
754 9b0c03e7 Serge Torres
                                        theVar = None):
755 9b0c03e7 Serge Torres
    """
756 9b0c03e7 Serge Torres
    Build a polynomial in the classical monomials (possibly lacunary) basis 
757 9b0c03e7 Serge Torres
    from a list of coefficients and a list of exponents. The polynomial is in
758 9b0c03e7 Serge Torres
    the polynomial field given as argument.
759 9b0c03e7 Serge Torres
    """
760 9b0c03e7 Serge Torres
    if len(coeffsList) != len(expsList):
761 9b0c03e7 Serge Torres
        return None
762 9b0c03e7 Serge Torres
    ## If no variable is given, "x" is used.
763 9b0c03e7 Serge Torres
    ## If no polyField is given, we fall back on a polynomial field on RR.
764 9b0c03e7 Serge Torres
    if theVar is None:
765 9b0c03e7 Serge Torres
        if polyField is None:
766 9b0c03e7 Serge Torres
            theVar = x
767 9b0c03e7 Serge Torres
            polyField = RR[theVar]
768 9b0c03e7 Serge Torres
        else:
769 9b0c03e7 Serge Torres
            theVar = var(polyField.variable_name())
770 e2eb9ccc Serge Torres
    else: ### theVar is set.
771 e2eb9ccc Serge Torres
        ### No polyField, fallback on RR[theVar].
772 9b0c03e7 Serge Torres
        if polyField is None:
773 9b0c03e7 Serge Torres
            polyField = RR[theVar]
774 e2eb9ccc Serge Torres
        else: ### Both the polyFiled and theVar are set: create a new polyField
775 e2eb9ccc Serge Torres
              #   with theVar. The original polyField is not affected by the 
776 e2eb9ccc Serge Torres
              #   change.
777 9b0c03e7 Serge Torres
            polyField = polyField.change_var(theVar)  
778 9b0c03e7 Serge Torres
    ## Seed the polynomial.
779 9b0c03e7 Serge Torres
    poly = polyField(0)
780 9b0c03e7 Serge Torres
    ## Append the terms.
781 9b0c03e7 Serge Torres
    for coeff, exp in zip(coeffsList, expsList):
782 9b0c03e7 Serge Torres
        poly += polyField(coeff * theVar^exp)
783 9b0c03e7 Serge Torres
    return poly
784 9b0c03e7 Serge Torres
# End cvp_polynomial_from_coeffs_and_exps.
785 9b0c03e7 Serge Torres
#
786 9cf1fb38 Serge Torres
def cvp_remez_all_poly_error_func_maxis(funct, 
787 9b0c03e7 Serge Torres
                                        maxDegree, 
788 9b0c03e7 Serge Torres
                                        lowerBound, 
789 9b0c03e7 Serge Torres
                                        upperBound,
790 9b0c03e7 Serge Torres
                                        precsList, 
791 9b0c03e7 Serge Torres
                                        realField = None,
792 9b0c03e7 Serge Torres
                                        contFracMaxErr = None):
793 9b0c03e7 Serge Torres
    """
794 9b0c03e7 Serge Torres
    For a given function f, a degree and an interval, compute the 
795 9b0c03e7 Serge Torres
    maxima of the (f-remez_d(f)) function and those of the (f-truncRemez_d(f)) 
796 9b0c03e7 Serge Torres
    function over the interval.
797 9b0c03e7 Serge Torres
    """
798 9cf1fb38 Serge Torres
    ## If no realField argument is given try to retrieve it from the 
799 9cf1fb38 Serge Torres
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
800 9cf1fb38 Serge Torres
    if realField is None:
801 9cf1fb38 Serge Torres
        try:
802 9cf1fb38 Serge Torres
            ### Force failure if parent does not have prec() member.
803 9cf1fb38 Serge Torres
            lowerBound.parent().prec()
804 9cf1fb38 Serge Torres
            ### If no exception is thrown, set realField.
805 9cf1fb38 Serge Torres
            realField = lowerBound.parent()
806 9cf1fb38 Serge Torres
        except:
807 9cf1fb38 Serge Torres
            realField = RR
808 9cf1fb38 Serge Torres
    #print "Real field:", realField
809 9cf1fb38 Serge Torres
    funcSa         = func
810 9cf1fb38 Serge Torres
    funcAsStringSa = func._assume_str().replace("_SAGE_VAR_","",100)
811 9cf1fb38 Serge Torres
    print "Function as a string:", funcAsStringSa
812 9cf1fb38 Serge Torres
    ## Create the Sollya version of the function and compute the
813 9cf1fb38 Serge Torres
    #  Remez approximant
814 9cf1fb38 Serge Torres
    funcSo  = pobyso_parse_string(funcAsStringSa)
815 9cf1fb38 Serge Torres
    pStarSo = pobyso_remez_canonical_sa_so(funcAsStringSa, 
816 9cf1fb38 Serge Torres
                                           maxDegree, 
817 9cf1fb38 Serge Torres
                                           lowerBound,
818 9cf1fb38 Serge Torres
                                           upperBound)
819 9cf1fb38 Serge Torres
    ## Compute the error function and its derivative
820 9cf1fb38 Serge Torres
    ### First create the error function with copies since they are needed later.
821 9cf1fb38 Serge Torres
    errorFuncSo = sollya_lib_build_function_sub(sollya_lib_copy_obj(pStarSo), 
822 9cf1fb38 Serge Torres
                                                sollya_lib_copy_obj(funcSo))
823 9cf1fb38 Serge Torres
    intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound)
824 9cf1fb38 Serge Torres
    diffErrorFuncSo = pobyso_diff_so_so(errorFuncSo)
825 9cf1fb38 Serge Torres
    pobyso_clear_obj(errorFuncSo)
826 9cf1fb38 Serge Torres
    ## Compute the zeros of the derivative.
827 9c97e92f Serge Torres
    errorFuncMaxisSo = pobyso_dirty_find_zeros_so_so(diffErrorFuncSo, intervalSo)
828 9cf1fb38 Serge Torres
    pobyso_clear_obj(diffErrorFuncSo)
829 9c97e92f Serge Torres
    errorFuncMaxisSa = pobyso_float_list_so_sa(errorFuncMaxisSo)
830 9c97e92f Serge Torres
    pobyso_clear_obj(errorFuncMaxisSo)
831 9cf1fb38 Serge Torres
    ## Compute the truncated Remez polynomial and the error function.
832 9cf1fb38 Serge Torres
    truncFormatListSo = pobyso_build_list_of_ints_sa_so(*precsList)
833 9cf1fb38 Serge Torres
    pTruncSo = pobyso_round_coefficients_so_so(pStarSo, truncFormatListSo)
834 9cf1fb38 Serge Torres
    pobyso_clear_obj(pStarSo)
835 9cf1fb38 Serge Torres
    ### Compute the error function. This time we consume both the function
836 9cf1fb38 Serge Torres
    #   and the polynomial.
837 9cf1fb38 Serge Torres
    errorFuncSo = sollya_lib_build_function_sub(pTruncSo, funcSo)
838 9cf1fb38 Serge Torres
    ## Compute the derivative.
839 9cf1fb38 Serge Torres
    diffErrorFuncSo = pobyso_diff_so_so(errorFuncSo)
840 9cf1fb38 Serge Torres
    pobyso_clear_obj(errorFuncSo)
841 9cf1fb38 Serge Torres
    ## Compute the zeros of the derivative.
842 9c97e92f Serge Torres
    errorFuncMaxisSo = pobyso_dirty_find_zeros_so_so(diffErrorFuncSo, intervalSo)
843 9cf1fb38 Serge Torres
    pobyso_clear_obj(diffErrorFuncSo)
844 9cf1fb38 Serge Torres
    pobyso_clear_obj(intervalSo)
845 9c97e92f Serge Torres
    errorFuncTruncMaxisSa = pobyso_float_list_so_sa(errorFuncMaxisSo)
846 9c97e92f Serge Torres
    pobyso_clear_obj(errorFuncMaxisSo)
847 9c97e92f Serge Torres
    ## Merge with the first list, removing duplicates if any.
848 9c97e92f Serge Torres
    errorFuncMaxisSa.extend(elem for elem in errorFuncTruncMaxisSa \
849 9c97e92f Serge Torres
                            if elem not in errorFuncMaxisSa)
850 9c97e92f Serge Torres
    errorFuncMaxisSa.sort()
851 9cf1fb38 Serge Torres
    ## If required, convert the numbers to rational numbers.
852 9cf1fb38 Serge Torres
    if not contFracMaxErr is None:
853 9c97e92f Serge Torres
        for index in xrange(0, len(errorFuncMaxisSa)):
854 9c97e92f Serge Torres
            errorFuncMaxisSa[index] = \
855 9c97e92f Serge Torres
                errorFuncMaxisSa[index].nearby_rational(contFracMaxErr)
856 9c97e92f Serge Torres
    return errorFuncMaxisSa
857 9cf1fb38 Serge Torres
# End cvp_remez_all_poly_error_func_maxis.
858 9b0c03e7 Serge Torres
#
859 724064f1 Serge Torres
def cvp_remez_all_poly_error_func_zeros(funct, 
860 724064f1 Serge Torres
                                        maxDegree, 
861 724064f1 Serge Torres
                                        lowerBound, 
862 724064f1 Serge Torres
                                        upperBound,
863 724064f1 Serge Torres
                                        precsList, 
864 04d64614 Serge Torres
                                        realField = None,
865 04d64614 Serge Torres
                                        contFracMaxErr = None):
866 724064f1 Serge Torres
    """
867 724064f1 Serge Torres
    For a given function f, a degree and an interval, compute the 
868 04d64614 Serge Torres
    zeros of the (f-remez_d(f)) function and those of the (f-truncRemez_d(f)) 
869 9cf1fb38 Serge Torres
    function over the interval.
870 724064f1 Serge Torres
    """
871 04d64614 Serge Torres
    ## If no realField argument is given try to retrieve it from the 
872 04d64614 Serge Torres
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
873 04d64614 Serge Torres
    if realField is None:
874 04d64614 Serge Torres
        try:
875 04d64614 Serge Torres
            ### Force failure if parent does not have prec() member.
876 04d64614 Serge Torres
            lowerBound.parent().prec()
877 04d64614 Serge Torres
            ### If no exception is thrown, set realField.
878 04d64614 Serge Torres
            realField = lowerBound.parent()
879 04d64614 Serge Torres
        except:
880 04d64614 Serge Torres
            realField = RR
881 04d64614 Serge Torres
    #print "Real field:", realField
882 724064f1 Serge Torres
    funcSa         = func
883 724064f1 Serge Torres
    funcAsStringSa = func._assume_str().replace("_SAGE_VAR_","",100)
884 724064f1 Serge Torres
    print "Function as a string:", funcAsStringSa
885 724064f1 Serge Torres
    ## Create the Sollya version of the function and compute the
886 724064f1 Serge Torres
    #  Remez approximant
887 724064f1 Serge Torres
    funcSo  = pobyso_parse_string(funcAsStringSa)
888 724064f1 Serge Torres
    pStarSo = pobyso_remez_canonical_sa_so(funcAsStringSa, 
889 724064f1 Serge Torres
                                           maxDegree, 
890 724064f1 Serge Torres
                                           lowerBound,
891 724064f1 Serge Torres
                                           upperBound)
892 724064f1 Serge Torres
    ## Compute the zeroes of the error function.
893 724064f1 Serge Torres
    ### First create the error function with copies since they are needed later.
894 724064f1 Serge Torres
    errorFuncSo = sollya_lib_build_function_sub(sollya_lib_copy_obj(pStarSo), 
895 724064f1 Serge Torres
                                                sollya_lib_copy_obj(funcSo))
896 04d64614 Serge Torres
    intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound)
897 724064f1 Serge Torres
    errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(errorFuncSo, intervalSo)
898 724064f1 Serge Torres
    pobyso_clear_obj(errorFuncSo) # Clears funcSo and pStarSo as well.
899 724064f1 Serge Torres
    #print "Zeroes of the error function from Sollya:"
900 724064f1 Serge Torres
    #pobyso_autoprint(errorFuncZerosSo)
901 724064f1 Serge Torres
    errorFuncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo)
902 724064f1 Serge Torres
    pobyso_clear_obj(errorFuncZerosSo)
903 724064f1 Serge Torres
    #print "\nZeroes of the error function from Sage:"
904 724064f1 Serge Torres
    #print errorFuncZerosSa
905 724064f1 Serge Torres
    #
906 724064f1 Serge Torres
    ## Deal with the truncated polynomial now.
907 724064f1 Serge Torres
    ### Create the formats list. Notice the "*" before the list variable name.
908 724064f1 Serge Torres
    truncFormatListSo = pobyso_build_list_of_ints_sa_so(*precsList)
909 9b0c03e7 Serge Torres
    #print "Precisions list as Sollya object:", 
910 9cf1fb38 Serge Torres
    #pobyso_autoprint(truncFormatListSo)
911 724064f1 Serge Torres
    pTruncSo = pobyso_round_coefficients_so_so(pStarSo, truncFormatListSo)
912 9b0c03e7 Serge Torres
    #print "Truncated polynomial:", ; pobyso_autoprint(pTruncSo)
913 724064f1 Serge Torres
    ### Compute the error function. This time we consume both the function
914 724064f1 Serge Torres
    #   and the polynomial.
915 724064f1 Serge Torres
    errorFuncSo = sollya_lib_build_function_sub(pTruncSo, 
916 724064f1 Serge Torres
                                                funcSo)
917 724064f1 Serge Torres
    errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(errorFuncSo, intervalSo)
918 724064f1 Serge Torres
    pobyso_clear_obj(pStarSo)
919 9b0c03e7 Serge Torres
    #print "Zeroes of the error function for the truncated polynomial from Sollya:"
920 9cf1fb38 Serge Torres
    #pobyso_autoprint(errorFuncZerosSo)
921 724064f1 Serge Torres
    errorFuncTruncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo)
922 724064f1 Serge Torres
    pobyso_clear_obj(errorFuncZerosSo)
923 724064f1 Serge Torres
    ## Sollya objects clean up.
924 724064f1 Serge Torres
    pobyso_clear_obj(intervalSo)
925 724064f1 Serge Torres
    errorFuncZerosSa += errorFuncTruncZerosSa
926 724064f1 Serge Torres
    errorFuncZerosSa.sort()
927 04d64614 Serge Torres
    ## If required, convert the numbers to rational numbers.
928 04d64614 Serge Torres
    if not contFracMaxErr is None:
929 04d64614 Serge Torres
        for index in xrange(0, len(errorFuncZerosSa)):
930 04d64614 Serge Torres
            errorFuncZerosSa[index] = \
931 04d64614 Serge Torres
                errorFuncZerosSa[index].nearby_rational(contFracMaxErr)
932 04d64614 Serge Torres
    return errorFuncZerosSa
933 04d64614 Serge Torres
    #
934 04d64614 Serge Torres
# End remez_all_poly_error_func_zeros
935 04d64614 Serge Torres
#
936 04d64614 Serge Torres
def cvp_remez_poly_error_func_zeros(funct, 
937 04d64614 Serge Torres
                                    maxDegree, 
938 04d64614 Serge Torres
                                    lowerBound, 
939 04d64614 Serge Torres
                                    upperBound,
940 04d64614 Serge Torres
                                    realField = None,
941 04d64614 Serge Torres
                                    contFracMaxErr = None):
942 04d64614 Serge Torres
    """
943 04d64614 Serge Torres
    For a given function f, a degree and an interval, compute the 
944 04d64614 Serge Torres
    zeros of the (f-remez_d(f)) function.
945 04d64614 Serge Torres
    """
946 04d64614 Serge Torres
    ## If no realField argument is given try to retrieve it from the 
947 04d64614 Serge Torres
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
948 04d64614 Serge Torres
    if realField is None:
949 04d64614 Serge Torres
        try:
950 04d64614 Serge Torres
            ### Force failure if parent does not have prec() member.
951 04d64614 Serge Torres
            lowerBound.parent().prec()
952 04d64614 Serge Torres
            ### If no exception is thrown, set realField.
953 04d64614 Serge Torres
            realField = lowerBound.parent()
954 04d64614 Serge Torres
        except:
955 04d64614 Serge Torres
            realField = RR
956 04d64614 Serge Torres
    #print "Real field:", realField
957 04d64614 Serge Torres
    funcSa         = func
958 04d64614 Serge Torres
    funcAsStringSa = func._assume_str().replace("_SAGE_VAR_","",100)
959 04d64614 Serge Torres
    #print "Function as a string:", funcAsStringSa
960 04d64614 Serge Torres
    ## Create the Sollya version of the function and compute the
961 04d64614 Serge Torres
    #  Remez approximant
962 04d64614 Serge Torres
    funcSo  = pobyso_parse_string(funcAsStringSa)
963 04d64614 Serge Torres
    pStarSo = pobyso_remez_canonical_sa_so(funcAsStringSa, 
964 04d64614 Serge Torres
                                           maxDegree, 
965 04d64614 Serge Torres
                                           lowerBound,
966 04d64614 Serge Torres
                                           upperBound)
967 04d64614 Serge Torres
    ## Compute the zeroes of the error function.
968 04d64614 Serge Torres
    ### Error function creation consumes both pStarSo and funcSo.
969 04d64614 Serge Torres
    errorFuncSo = sollya_lib_build_function_sub(pStarSo, funcSo)
970 04d64614 Serge Torres
    intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound)
971 04d64614 Serge Torres
    errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(errorFuncSo, intervalSo)
972 04d64614 Serge Torres
    pobyso_clear_obj(errorFuncSo) # Clears funcSo and pStarSo as well.
973 04d64614 Serge Torres
    #print "Zeroes of the error function from Sollya:"
974 04d64614 Serge Torres
    #pobyso_autoprint(errorFuncZerosSo)
975 04d64614 Serge Torres
    errorFuncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo)
976 04d64614 Serge Torres
    pobyso_clear_obj(errorFuncZerosSo)
977 04d64614 Serge Torres
    ## Sollya objects clean up.
978 04d64614 Serge Torres
    pobyso_clear_obj(intervalSo)
979 04d64614 Serge Torres
    ## Converting to rational numbers, if required.
980 04d64614 Serge Torres
    if not contFracMaxErr is None:
981 04d64614 Serge Torres
        for index in xrange(0, len(errorFuncZerosSa)):
982 04d64614 Serge Torres
            errorFuncZerosSa[index] = \
983 04d64614 Serge Torres
                errorFuncZerosSa[index].nearby_rational(contFracMaxErr)
984 724064f1 Serge Torres
    return errorFuncZerosSa
985 724064f1 Serge Torres
    #
986 724064f1 Serge Torres
# End remez_poly_error_func_zeros
987 724064f1 Serge Torres
#
988 62861417 Serge Torres
def cvp_round_to_bits(num, numBits):
989 62861417 Serge Torres
    """
990 62861417 Serge Torres
    Round "num" to "numBits" bits.
991 62861417 Serge Torres
    @param num    : the number to round;
992 62861417 Serge Torres
    @param numBits: the number of bits to round to.
993 62861417 Serge Torres
    """
994 62861417 Serge Torres
    if num == 0:
995 62861417 Serge Torres
        return num
996 62861417 Serge Torres
    log2ofNum  = 0
997 62861417 Serge Torres
    numRounded = 0
998 62861417 Serge Torres
    ## Avoid conversion to floating-point if not necessary.
999 62861417 Serge Torres
    try:
1000 62861417 Serge Torres
        log2OfNum = num.abs().log2()
1001 62861417 Serge Torres
    except:
1002 62861417 Serge Torres
        log2OfNum = RR(num).abs().log2()
1003 62861417 Serge Torres
    ## Works equally well for num >= 1 and num < 1.
1004 62861417 Serge Torres
    log2OfNum = ceil(log2OfNum)
1005 62861417 Serge Torres
    # print "cvp_round_to_bits - Log2OfNum:", log2OfNum
1006 62861417 Serge Torres
    divMult = log2OfNum - numBits
1007 62861417 Serge Torres
    #print "cvp_round_to_bits - DivMult:", divMult
1008 62861417 Serge Torres
    if divMult != 0:
1009 62861417 Serge Torres
        numRounded = round(num/2^divMult) * 2^divMult
1010 62861417 Serge Torres
    else:
1011 62861417 Serge Torres
        numRounded = num
1012 62861417 Serge Torres
    return numRounded
1013 62861417 Serge Torres
# End cvp_round_to_bits
1014 62861417 Serge Torres
#
1015 9645ea29 Serge Torres
def cvp_vector_in_basis(vect, basis):
1016 9645ea29 Serge Torres
    """
1017 9645ea29 Serge Torres
    Compute the coordinates of "vect" in "basis" by
1018 9645ea29 Serge Torres
    solving a linear system.
1019 9cf1fb38 Serge Torres
    @param vect  the vector we want to compute the coordinates of
1020 9645ea29 Serge Torres
                  in coordinates of the ambient space;
1021 9cf1fb38 Serge Torres
    @param basis the basis we want to compute the coordinates in
1022 9645ea29 Serge Torres
                  as a matrix relative to the ambient space.
1023 9645ea29 Serge Torres
    """
1024 9645ea29 Serge Torres
    ## Create the variables for the linear equations.
1025 9645ea29 Serge Torres
    varDeclString = ""
1026 9645ea29 Serge Torres
    basisIterationsRange = xrange(0, basis.nrows())
1027 9645ea29 Serge Torres
    ### Building variables declaration string.
1028 9645ea29 Serge Torres
    for index in basisIterationsRange:
1029 9645ea29 Serge Torres
        varName = "a" + str(index)
1030 9645ea29 Serge Torres
        if varDeclString == "":
1031 9645ea29 Serge Torres
            varDeclString += varName
1032 9645ea29 Serge Torres
        else:
1033 9645ea29 Serge Torres
            varDeclString += "," + varName
1034 9645ea29 Serge Torres
    ### Variables declaration
1035 9645ea29 Serge Torres
    varsList = var(varDeclString)
1036 9645ea29 Serge Torres
    sage_eval("var('" + varDeclString + "')")
1037 9645ea29 Serge Torres
    ## Create the equations
1038 9645ea29 Serge Torres
    equationString = ""
1039 9645ea29 Serge Torres
    equationsList = []
1040 9645ea29 Serge Torres
    for vIndex in xrange(0, len(vect)):
1041 9645ea29 Serge Torres
        equationString = ""
1042 9645ea29 Serge Torres
        for bIndex in basisIterationsRange:
1043 9645ea29 Serge Torres
            if equationString != "":
1044 9645ea29 Serge Torres
                equationString += "+"
1045 9645ea29 Serge Torres
            equationString += str(varsList[bIndex]) + "*" + str(basis[bIndex,vIndex])
1046 9645ea29 Serge Torres
        equationString += " == " + str(vect[vIndex])
1047 9645ea29 Serge Torres
        equationsList.append(sage_eval(equationString))
1048 9cf1fb38 Serge Torres
    ## Solve the equations system. The solution dictionary is needed
1049 9645ea29 Serge Torres
    #  to recover the values of the solutions.
1050 9645ea29 Serge Torres
    solutions = solve(equationsList,varsList, solution_dict=True)
1051 9cf1fb38 Serge Torres
    ## This code is deactivated: did not solve the problem.
1052 9cf1fb38 Serge Torres
    """
1053 9cf1fb38 Serge Torres
    if len(solutions) == 0:
1054 9cf1fb38 Serge Torres
        print "Trying Maxima to_poly_sove."
1055 9cf1fb38 Serge Torres
        solutions = solve(equationsList,varsList, solution_dict=True, to_poly_solve = 'force')
1056 9cf1fb38 Serge Torres
    """
1057 9645ea29 Serge Torres
    #print "Solutions:", s
1058 9645ea29 Serge Torres
    ## Recover solutions in rational components vector.
1059 9645ea29 Serge Torres
    vectInBasis = vector(QQ, basis.nrows())
1060 9645ea29 Serge Torres
    ### There can be several solution, in the general case.
1061 9cf1fb38 Serge Torres
    #   Here, there is only one (or none). For each solution, each 
1062 9645ea29 Serge Torres
    #   variable has to be searched for.
1063 9645ea29 Serge Torres
    for sol in solutions:
1064 9645ea29 Serge Torres
        for bIndex in basisIterationsRange:
1065 9645ea29 Serge Torres
            vectInBasis[bIndex] = sol[varsList[bIndex]]
1066 9645ea29 Serge Torres
    return vectInBasis
1067 9645ea29 Serge Torres
# End cpv_vector_in_basis.
1068 9645ea29 Serge Torres
#
1069 94c8237b Serge Torres
sys.stderr.write("... functions for CVP loaded.\n")