Révision 62861417 src/functions_for_cvp.sage
b/src/functions_for_cvp.sage | ||
---|---|---|
15 | 15 |
""" |
16 | 16 |
## A deep copy is not necessary here. |
17 | 17 |
curVect = copy(vect) |
18 |
print "Vector:", vect |
|
18 |
print "cvp_babai - Vector:", vect
|
|
19 | 19 |
## From index of last row down to 0. |
20 | 20 |
for vIndex in xrange(len(redBasis.rows())-1, -1, -1): |
21 | 21 |
curRBGSO = redBasisGso.row(vIndex) |
22 | 22 |
curVect = curVect - (round((curVect * curRBGSO) / (curRBGSO * curRBGSO)) * redBasis.row(vIndex)) |
23 | 23 |
return vect - curVect |
24 |
# End cvp_babai |
|
24 | 25 |
# |
25 |
|
|
26 | 26 |
def cvp_bkz_reduce(intBasis, blockSize): |
27 | 27 |
""" |
28 | 28 |
Thin and simplistic wrapper the HKZ function of the FP_LLL module. |
... | ... | |
32 | 32 |
return fplllIntBasis._sage_() |
33 | 33 |
# End cvp_hkz_reduce. |
34 | 34 |
# |
35 |
|
|
36 |
def cvp_common_scaling_factor(floatBasis, |
|
37 |
funcVect, |
|
38 |
precision , |
|
39 |
precisionFraction = None): |
|
35 |
def cvp_common_scaling_exp(precision, |
|
36 |
precisionFraction = None): |
|
40 | 37 |
""" |
41 | 38 |
Compute the common scaling factor (a power of 2). |
42 |
The exponent is made of: |
|
43 |
- a fraction of the precision; |
|
44 |
- an integer depending on the smallest norm of the vectors of the basis. |
|
39 |
The exponent is a fraction of the precision; |
|
40 |
A extra factor is computed for the vector, |
|
41 |
exra factors are computed for the basis vectors, all in the corresponding |
|
42 |
functions. |
|
45 | 43 |
""" |
46 | 44 |
## Set a default value for the precisionFraction to 1/2. |
47 | 45 |
if precisionFraction is None: |
48 |
precisionFraction = 1/2 |
|
49 |
## Compute the norms of the vectors and get the smallest one. |
|
50 |
# Start with "oo" (+Infinty) |
|
46 |
precisionFraction = 3/4 |
|
47 |
""" |
|
51 | 48 |
minBasisVectsNorm = oo |
52 | 49 |
currentNorm = 0 |
53 | 50 |
for vect in floatBasis.rows(): |
... | ... | |
66 | 63 |
if powerForMinNorm < 0: |
67 | 64 |
return 2^(ceil(precision*precisionFraction) - powerFromMinNorm) |
68 | 65 |
else: |
69 |
return 2^(ceil(precision*precisionFraction)) |
|
66 |
""" |
|
67 |
return ceil(precision * precisionFraction) |
|
70 | 68 |
# End cvp_common_scaling_factor. |
71 | 69 |
# |
72 |
def cvp_extra_scaling_factor(floatBasis, |
|
73 |
funcVect, |
|
74 |
coeffsPrecList, |
|
75 |
minExponentsList): |
|
70 |
def cvp_extra_basis_scaling_exps(precsList, minExponentsList): |
|
71 |
extraScalingExpsList = [] |
|
72 |
for minExp, prec in zip(minExponentsList, precsList): |
|
73 |
if minExp - prec < 0: |
|
74 |
extraScalingExpsList.append(minExp - prec) |
|
75 |
else: |
|
76 |
extraScalingExpsList.append(0) |
|
77 |
return extraScalingExpsList |
|
78 |
# End cvp_extra_basis_scaling_exps. |
|
79 |
# |
|
80 |
def cvp_extra_function_scaling_exp(floatBasis, |
|
81 |
floatFuncVect, |
|
82 |
maxExponentsList): |
|
76 | 83 |
""" |
77 |
Compute the extra scaling factor for each element of the basis. |
|
84 |
Compute the extra scaling exponent for the function vector in ordre to |
|
85 |
guarantee that the maximum exponent can be reached for each element of the |
|
86 |
basis. |
|
78 | 87 |
""" |
88 |
## Check arguments |
|
79 | 89 |
if floatBasis.nrows() == 0 or \ |
80 | 90 |
floatBasis.ncols() == 0 or \ |
81 |
len(funcVect) == 0: |
|
82 |
return 0 |
|
83 |
## Compute the norm of the function vector. |
|
84 |
funcVectNorm = funcVect.norm() |
|
91 |
len(floatFuncVect) == 0: |
|
92 |
return 1 |
|
93 |
if len(maxExponentsList) != floatBasis.nrows(): |
|
94 |
return None |
|
95 |
## Compute the log of the norm of the function vector. |
|
96 |
funcVectNormLog = log(floatFuncVect.norm()) |
|
85 | 97 |
## Compute the extra scaling factor for each vector of the basis. |
86 |
### Pass #1 for norms ratios an minExponentsList |
|
87 |
scalingPowers = [] |
|
88 |
normsRatio = 0 |
|
89 |
for (row, maxExp) in zip(floatBasis.rows(),minExponentsList): |
|
90 |
normsRatio = funcVectNorm / row.norm() |
|
91 |
normsRatioLog2 = normsRatio.log2().floor() |
|
92 |
print "Current norms ratio:", normsRatio, normsRatioLog2 |
|
93 |
scalingPower = normsRatioLog2 + maxExp |
|
94 |
print "Current scaling power:", scalingPower |
|
95 |
scalingPowers.append(scalingPower) |
|
96 |
### Pass #2 for coefficients precision. |
|
97 |
minScalingPower = oo |
|
98 |
for index in xrange(0,len(scalingPowers)): |
|
99 |
scalingPowers[index] -= coeffsPrecList[index] |
|
100 |
if scalingPowers[index] < minScalingPower: |
|
101 |
minScalingPower = scalingPowers[index] |
|
102 |
print "Current scaling power:", scalingPowers[index] |
|
103 |
if minScalingPower < 0: |
|
104 |
scalingFactor = 2^(-minScalingPower) |
|
105 |
else: |
|
106 |
scalingFactor = 1 |
|
107 |
return (scalingFactor, scalingPowers) |
|
108 |
# End cvp_extra_scaling_factor. |
|
98 |
# for norms ratios an maxExponentsList. |
|
99 |
extraScalingExp = 0 |
|
100 |
for (row, maxExp) in zip(floatBasis.rows(),maxExponentsList): |
|
101 |
rowNormLog = log(row.norm()) |
|
102 |
normsRatioLog2 = floor((funcVectNormLog - rowNormLog) / log2) |
|
103 |
#print "Current norms ratio log2:", normsRatioLog2 |
|
104 |
scalingExpCandidate = normsRatioLog2 - maxExp |
|
105 |
#print "Current scaling exponent candidate:", scalingExpCandidate |
|
106 |
if scalingExpCandidate < 0: |
|
107 |
if -scalingExpCandidate > extraScalingExp: |
|
108 |
extraScalingExp = -scalingExpCandidate |
|
109 |
return extraScalingExp |
|
110 |
# End cvp_extra_function_scaling_exp. |
|
109 | 111 |
# |
110 | 112 |
def cvp_float_basis(monomialsList, pointsList, realField): |
111 | 113 |
""" |
... | ... | |
152 | 154 |
return fplllIntBasis._sage_() |
153 | 155 |
# End cvp_hkz_reduce. |
154 | 156 |
# |
155 |
def cvp_int_basis(floatBasis, commonScalingFactor): |
|
157 |
def cvp_int_basis(floatBasis, |
|
158 |
commonScalingExp, |
|
159 |
extraScalingExpsList): |
|
156 | 160 |
""" |
157 |
From the float basis and the common scaling factor, compute the
|
|
158 |
integral basis. |
|
161 |
From the float basis, the common scaling factor and the extra exponents
|
|
162 |
compute the integral basis.
|
|
159 | 163 |
""" |
164 |
## Checking arguments. |
|
165 |
if floatBasis.nrows() != len(extraScalingExpsList): |
|
166 |
return None |
|
160 | 167 |
intBasis = matrix(ZZ, floatBasis.nrows(), floatBasis.ncols()) |
161 | 168 |
for rIndex in xrange(0, floatBasis.nrows()): |
162 | 169 |
for cIndex in xrange(0, floatBasis.ncols()): |
163 | 170 |
intBasis[rIndex, cIndex] = \ |
164 |
floatBasis[rIndex, cIndex] * commonScalingFactor |
|
171 |
floatBasis[rIndex, cIndex] * \ |
|
172 |
2^(commonScalingExp + extraScalingExpsList[rIndex]) |
|
165 | 173 |
return intBasis |
166 | 174 |
# End cvp_int_basis. |
167 | 175 |
# |
168 |
def cvp_int_vector_for_approx(floatVect, commonScalingFactor, extraScalingFactor):
|
|
169 |
totalScalingFactor = commonScalingFactor * extraScalingFactor
|
|
176 |
def cvp_int_vector_for_approx(floatVect, commonScalingExp, extraScalingExp):
|
|
177 |
totalScalingFactor = 2^(commonScalingExp + extraScalingExp)
|
|
170 | 178 |
intVect = vector(ZZ, len(floatVect)) |
171 | 179 |
for index in xrange(0, len(floatVect)): |
172 | 180 |
intVect[index] = (floatVect[index] * totalScalingFactor).round() |
... | ... | |
194 | 202 |
return monomialsList |
195 | 203 |
# End cvp_monomials_list. |
196 | 204 |
# |
205 |
def cvp_polynomial_coeffs_from_vect(cvpVectInBasis, |
|
206 |
coeffsPrecList, |
|
207 |
minCoeffsExpList, |
|
208 |
extraFuncScalingExp): |
|
209 |
numElements = len(cvpVectInBasis) |
|
210 |
## Arguments check. |
|
211 |
if numElements != len(minCoeffsExpList) or \ |
|
212 |
numElements != len(coeffsPrecList): |
|
213 |
return None |
|
214 |
polynomialCoeffsList = [] |
|
215 |
for index in xrange(0, numElements): |
|
216 |
currentCoeff = cvp_round_to_bits(cvpVectInBasis[index], |
|
217 |
coeffsPrecList[index]) |
|
218 |
print "cvp_polynomial_coeffs - current coefficient rounded:", currentCoeff |
|
219 |
currentCoeff *= 2^(minCoeffsExpList[index]) |
|
220 |
print "cvp_polynomial_coeffs - current coefficient scaled :", currentCoeff |
|
221 |
currentCoeff *= 2^(-coeffsPrecList[index]) |
|
222 |
print "cvp_polynomial_coeffs - current coefficient prec corrected :", currentCoeff |
|
223 |
currentCoeff *= 2^(-extraFuncScalingExp) |
|
224 |
print "cvp_polynomial_coeffs - current coefficient extra func scaled :", currentCoeff |
|
225 |
polynomialCoeffsList.append(currentCoeff) |
|
226 |
return polynomialCoeffsList |
|
227 |
# En polynomial_coeffs_from_vect. |
|
228 |
# |
|
229 |
def cvp_round_to_bits(num, numBits): |
|
230 |
""" |
|
231 |
Round "num" to "numBits" bits. |
|
232 |
@param num : the number to round; |
|
233 |
@param numBits: the number of bits to round to. |
|
234 |
""" |
|
235 |
if num == 0: |
|
236 |
return num |
|
237 |
log2ofNum = 0 |
|
238 |
numRounded = 0 |
|
239 |
## Avoid conversion to floating-point if not necessary. |
|
240 |
try: |
|
241 |
log2OfNum = num.abs().log2() |
|
242 |
except: |
|
243 |
log2OfNum = RR(num).abs().log2() |
|
244 |
## Works equally well for num >= 1 and num < 1. |
|
245 |
log2OfNum = ceil(log2OfNum) |
|
246 |
# print "cvp_round_to_bits - Log2OfNum:", log2OfNum |
|
247 |
divMult = log2OfNum - numBits |
|
248 |
#print "cvp_round_to_bits - DivMult:", divMult |
|
249 |
if divMult != 0: |
|
250 |
numRounded = round(num/2^divMult) * 2^divMult |
|
251 |
else: |
|
252 |
numRounded = num |
|
253 |
return numRounded |
|
254 |
# End cvp_round_to_bits |
|
255 |
# |
|
197 | 256 |
def cvp_vector_in_basis(vect, basis): |
198 | 257 |
""" |
199 | 258 |
Compute the coordinates of "vect" in "basis" by |
Formats disponibles : Unified diff