Révision 212

pobysoPythonSage/src/sageSLZ/sageSLZ.sage (revision 212)
230 230
    return ccReducedPolynomialsList
231 231
# End slz_compute_coppersmith_reduced_polynomials
232 232

  
233
def slz_compute_coppersmith_reduced_polynomials_with_lattice_volume(inputPolynomial,
234
                                                                    alpha,
235
                                                                    N,
236
                                                                    iBound,
237
                                                                    tBound):
238
    """
239
    For a given set of arguments (see below), compute a list
240
    of "reduced polynomials" that could be used to compute roots
241
    of the inputPolynomial.
242
    Print the volume of the initial basis as well.
243
    INPUT:
244
    
245
    - "inputPolynomial" -- (no default) a bivariate integer polynomial;
246
    - "alpha" -- the alpha parameter of the Coppersmith algorithm;
247
    - "N" -- the modulus;
248
    - "iBound" -- the bound on the first variable;
249
    - "tBound" -- the bound on the second variable.
250
    
251
    OUTPUT:
252
    
253
    A list of bivariate integer polynomial obtained using the Coppersmith
254
    algorithm. The polynomials correspond to the rows of the LLL-reduce
255
    reduced base that comply with the Coppersmith condition.
256
    """
257
    # Arguments check.
258
    if iBound == 0 or tBound == 0:
259
        return None
260
    # End arguments check.
261
    nAtAlpha = N^alpha
262
    ## Building polynomials for matrix.
263
    polyRing   = inputPolynomial.parent()
264
    # Whatever the 2 variables are actually called, we call them
265
    # 'i' and 't' in all the variable names.
266
    (iVariable, tVariable) = inputPolynomial.variables()[:2]
267
    #print polyVars[0], type(polyVars[0])
268
    initialPolynomial = inputPolynomial.subs({iVariable:iVariable * iBound,
269
                                              tVariable:tVariable * tBound})
270
##    polynomialsList = \
271
##        spo_polynomial_to_polynomials_list_8(initialPolynomial,
272
##        spo_polynomial_to_polynomials_list_5(initialPolynomial,
273
    polynomialsList = \
274
        spo_polynomial_to_polynomials_list_5(initialPolynomial,
275
                                             alpha,
276
                                             N,
277
                                             iBound,
278
                                             tBound,
279
                                             0)
280
    #print "Polynomials list:", polynomialsList
281
    ## Building the proto matrix.
282
    knownMonomials = []
283
    protoMatrix    = []
284
    for poly in polynomialsList:
285
        spo_add_polynomial_coeffs_to_matrix_row(poly,
286
                                                knownMonomials,
287
                                                protoMatrix,
288
                                                0)
289
    matrixToReduce = spo_proto_to_row_matrix(protoMatrix)
290
    matrixToReduceTranspose = matrixToReduce.transpose()
291
    squareMatrix = matrixToReduce * matrixToReduceTranspose
292
    squareMatDet = det(squareMatrix)
293
    latticeVolume = sqrt(squareMatDet)
294
    print "Lattice volume:", latticeVolume.n()
295
    print "Lattice volume / N:", (latticeVolume/N).n()
296
    #print matrixToReduce
297
    ## Reduction and checking.
298
    ## S.T. changed 'fp' to None as of Sage 6.6 complying to
299
    #  error message issued when previous code was used.
300
    #reducedMatrix = matrixToReduce.LLL(fp='fp')
301
    reductionTimeStart = cputime() 
302
    reducedMatrix = matrixToReduce.LLL(fp=None)
303
    reductionTime = cputime(reductionTimeStart)
304
    print "Reduction time:", reductionTime
305
    isLLLReduced  = reducedMatrix.is_LLL_reduced()
306
    if not isLLLReduced:
307
        return None
308
    monomialsCount     = len(knownMonomials)
309
    monomialsCountSqrt = sqrt(monomialsCount)
310
    #print "Monomials count:", monomialsCount, monomialsCountSqrt.n()
311
    #print reducedMatrix
312
    ## Check the Coppersmith condition for each row and build the reduced 
313
    #  polynomials.
314
    ccReducedPolynomialsList = []
315
    for row in reducedMatrix.rows():
316
        l2Norm = row.norm(2)
317
        if (l2Norm * monomialsCountSqrt) < nAtAlpha:
318
            #print (l2Norm * monomialsCountSqrt).n()
319
            #print l2Norm.n()
320
            ccReducedPolynomial = \
321
                slz_compute_reduced_polynomial(row,
322
                                               knownMonomials,
323
                                               iVariable,
324
                                               iBound,
325
                                               tVariable,
326
                                               tBound)
327
            if not ccReducedPolynomial is None:
328
                ccReducedPolynomialsList.append(ccReducedPolynomial)
329
        else:
330
            #print l2Norm.n() , ">", nAtAlpha
331
            pass
332
    if len(ccReducedPolynomialsList) < 2:
333
        print "Less than 2 Coppersmith condition compliant vectors."
334
        return ()
335
    #print ccReducedPolynomialsList
336
    return ccReducedPolynomialsList
337
# End slz_compute_coppersmith_reduced_polynomials_with_lattice volume
338

  
233 339
def slz_compute_integer_polynomial_modular_roots(inputPolynomial,
234 340
                                                 alpha,
235 341
                                                 N,
pobysoPythonSage/src/sageSLZ/runSLZ-03.sage (revision 212)
26 26
RRR = RealField(precision)
27 27
intervalCenter      = RRR("1.9E9CBBFD6080B",16)  * 2^-31
28 28
icUlp               = intervalCenter.ulp()
29
intervalRadiusInUlp = 2^50          
30
#intervalRadiusInUlp = 2^49 + 2^45          
31
srs_run_SLZ_v02(inputFunction=func, 
32
                inputLowerBound = intervalCenter - icUlp * (intervalRadiusInUlp+128), 
33
                inputUpperBound = intervalCenter + icUlp * (intervalRadiusInUlp+128), 
29
intervalRadiusInUlp = 2^49 + 2^45          
30
srs_run_SLZ_v03(inputFunction=func, 
31
                inputLowerBound = RRR(1) * 2^-31, 
32
                inputUpperBound = RRR(1) * 2^-30 - icUlp, 
34 33
                alpha           = 2, 
35 34
                degree          = 2, 
36 35
                precision       = 53, 
pobysoPythonSage/src/sageSLZ/runSLZlv-01.sage (revision 212)
1
#! /opt/sage/sage
2
# @file runSLZ-03.sage
3
#
4
def initialize_env():
5
    """
6
    Load all necessary modules.
7
    """
8
    if not 'mpfi' in sage.misc.cython.standard_libs:
9
        sage.misc.cython.standard_libs.append('mpfi')
10
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sollya_lib.sage")
11
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageMpfr.spyx")
12
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/pobyso.py")
13
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageSLZ.sage")
14
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageNumericalOperations.sage")
15
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageRationalOperations.sage")
16
    # Matrix operations are loaded by polynomial operations.
17
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sagePolynomialOperations.sage")
18
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageRunSLZ.sage")
19

  
20

  
21
print "Running SLZ..."
22
initialize_env()
23
x = var('x')
24
func(x) = exp(x)
25
precision = 53
26
RRR = RealField(precision)
27
intervalCenter      = RRR("1.9E9CBBFD6080B",16)  * 2^-31
28
icUlp               = intervalCenter.ulp()
29
intervalRadiusInUlp = 2^49 + 2^45          
30
srs_compute_lattice_volume(inputFunction=func, 
31
                           inputLowerBound = RRR(1) * 2^-31, 
32
                           inputUpperBound = RRR(1) * 2^-30 - icUlp, 
33
                           alpha           = 4, 
34
                           degree          = 4, 
35
                           precision       = 53, 
36
                           emin            = -1022, 
37
                           emax            = 1023, 
38
                           targetHardnessToRound =  precision+50, 
39
                           debug           = True)
40
#
41
"""
42
srs_run_SLZ_v02(inputFunction=func, 
43
                inputLowerBound = RRR(1) * 2^-31, 
44
                inputUpperBound = RRR(1) * 2^-30 - icUlp, 
45
                alpha           = 2, 
46
                degree          = 2, 
47
                precision       = 53, 
48
                emin            = -1022, 
49
                emax            = 1023, 
50
                targetHardnessToRound =  precision+50, 
51
                debug           = True)
52
"""
53
"""
54
srs_run_SLZ_v01(inputFunction=func, 
55
                inputLowerBound = 402653184/1073741824, 
56
                inputUpperBound = 402653185/1073741824, 
57
                alpha = 2, 
58
                degree = 10, 
59
                precision = 53, 
60
                emin = -1022, 
61
                emax = 1023, 
62
                targetHardnessToRound =  precision+50, 
63
                debug = True)
64

  
65
#inputUpperBound = RRR(1/2) - RRR(1/4).ulp(), 
66
RR("1.9E9CBBFD6080B",16)  * 2^-31]
67
"""
0 68

  
pobysoPythonSage/src/sageSLZ/sageRunSLZ.sage (revision 212)
243 243
        reductionTime                     = cputime()
244 244
        # Compute the reduced polynomials.
245 245
        ccReducedPolynomialsList =  \
246
            slz_compute_coppersmith_reduced_polynomials(intIntP, 
247
                                                        alpha, 
248
                                                        N, 
249
                                                        iBound, 
250
                                                        tBound)
246
                slz_compute_coppersmith_reduced_polynomials(intIntP, 
247
                                                            alpha, 
248
                                                            N, 
249
                                                            iBound, 
250
                                                            tBound)
251 251
        if ccReducedPolynomialsList is None:
252 252
            raise Exception("Reduction failed.")
253 253
        reductionsFullTime    += cputime(reductionTime)
......
709 709
        reductionTime                     = cputime()
710 710
        #### Compute the reduced polynomials.
711 711
        ccReducedPolynomialsList =  \
712
            slz_compute_coppersmith_reduced_polynomials(intIntP, 
713
                                                        alpha, 
714
                                                        N, 
715
                                                        iBound, 
716
                                                        tBound)
712
                slz_compute_coppersmith_reduced_polynomials(intIntP, 
713
                                                            alpha, 
714
                                                            N, 
715
                                                            iBound, 
716
                                                            tBound)
717 717
        if ccReducedPolynomialsList is None:
718 718
            raise Exception("Reduction failed.")
719 719
        reductionsFullTime    += cputime(reductionTime)
......
937 937
    ## Output counters
938 938
# End srs_runSLZ-v02
939 939

  
940
def srs_run_SLZ_v03(inputFunction,
941
                    inputLowerBound,
942
                    inputUpperBound,
943
                    alpha,
944
                    degree,
945
                    precision,
946
                    emin,
947
                    emax,
948
                    targetHardnessToRound,
949
                    debug = False):
950
    """
951
    Changes from V2:
952
        Root search is changed:
953
            - we compute the resultants in i and in t;
954
            - we compute the roots set of each of these resultants;
955
            - we combine all the possible pairs between the two sets;
956
            - we check these pairs in polynomials for correctness.
957
    Changes from V1: 
958
        1- check for roots as soon as a resultant is computed;
959
        2- once a non null resultant is found, check for roots;
960
        3- constant resultant == no root.
961
    """
962

  
963
    if debug:
964
        print "Function                :", inputFunction
965
        print "Lower bound             :", inputLowerBound
966
        print "Upper bounds            :", inputUpperBound
967
        print "Alpha                   :", alpha
968
        print "Degree                  :", degree
969
        print "Precision               :", precision
970
        print "Emin                    :", emin
971
        print "Emax                    :", emax
972
        print "Target hardness-to-round:", targetHardnessToRound
973
        print
974
    ## Important constants.
975
    ### Stretch the interval if no error happens.
976
    noErrorIntervalStretch = 1 + 2^(-5)
977
    ### If no vector validates the Coppersmith condition, shrink the interval
978
    #   by the following factor.
979
    noCoppersmithIntervalShrink = 1/2
980
    ### If only (or at least) one vector validates the Coppersmith condition, 
981
    #   shrink the interval by the following factor.
982
    oneCoppersmithIntervalShrink = 3/4
983
    #### If only null resultants are found, shrink the interval by the 
984
    #    following factor.
985
    onlyNullResultantsShrink     = 3/4
986
    ## Structures.
987
    RRR         = RealField(precision)
988
    RRIF        = RealIntervalField(precision)
989
    ## Converting input bound into the "right" field.
990
    lowerBound = RRR(inputLowerBound)
991
    upperBound = RRR(inputUpperBound)
992
    ## Before going any further, check domain and image binade conditions.
993
    print inputFunction(1).n()
994
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
995
    if output is None:
996
        print "Invalid domain/image binades. Domain:",\
997
        lowerBound, upperBound, "Images:", \
998
        inputFunction(lowerBound), inputFunction(upperBound)
999
        raise Exception("Invalid domain/image binades.")
1000
    lb = output[0] ; ub = output[1]
1001
    if lb != lowerBound or ub != upperBound:
1002
        print "lb:", lb, " - ub:", ub
1003
        print "Invalid domain/image binades. Domain:",\
1004
        lowerBound, upperBound, "Images:", \
1005
        inputFunction(lowerBound), inputFunction(upperBound)
1006
        raise Exception("Invalid domain/image binades.")
1007
    #
1008
    ## Progam initialization
1009
    ### Approximation polynomial accuracy and hardness to round.
1010
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
1011
    polyTargetHardnessToRound = targetHardnessToRound + 1
1012
    ### Significand to integer conversion ratio.
1013
    toIntegerFactor           = 2^(precision-1)
1014
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
1015
    ### Variables and rings for polynomials and root searching.
1016
    i=var('i')
1017
    t=var('t')
1018
    inputFunctionVariable = inputFunction.variables()[0]
1019
    function = inputFunction.subs({inputFunctionVariable:i})
1020
    #  Polynomial Rings over the integers, for root finding.
1021
    Zi = ZZ[i]
1022
    Zt = ZZ[t]
1023
    Zit = ZZ[i,t]
1024
    ## Number of iterations limit.
1025
    maxIter = 100000
1026
    #
1027
    ## Compute the scaled function and the degree, in their Sollya version 
1028
    #  once for all.
1029
    (scaledf, sdlb, sdub, silb, siub) = \
1030
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
1031
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
1032
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
1033
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
1034
    #
1035
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
1036
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
1037
    (unscalingFunction, scalingFunction) = \
1038
        slz_interval_scaling_expression(domainBoundsInterval, i)
1039
    #print scalingFunction, unscalingFunction
1040
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
1041
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
1042
    if internalSollyaPrec < 192:
1043
        internalSollyaPrec = 192
1044
    pobyso_set_prec_sa_so(internalSollyaPrec)
1045
    print "Sollya internal precision:", internalSollyaPrec
1046
    ## Some variables.
1047
    ### General variables
1048
    lb                  = sdlb
1049
    ub                  = sdub
1050
    nbw                 = 0
1051
    intervalUlp         = ub.ulp()
1052
    #### Will be set by slz_interval_and_polynomila_to_sage.
1053
    ic                  = 0 
1054
    icAsInt             = 0    # Set from ic.
1055
    solutionsSet        = set()
1056
    tsErrorWidth        = []
1057
    csErrorVectors      = []
1058
    csVectorsResultants = []
1059
    floatP              = 0  # Taylor polynomial.
1060
    floatPcv            = 0  # Ditto with variable change.
1061
    intvl               = "" # Taylor interval
1062
    terr                = 0  # Taylor error.
1063
    iterCount = 0
1064
    htrnSet = set()
1065
    ### Timers and counters.
1066
    wallTimeStart                   = 0
1067
    cpuTimeStart                    = 0
1068
    taylCondFailedCount             = 0
1069
    coppCondFailedCount             = 0
1070
    resultCondFailedCount           = 0
1071
    coppCondFailed                  = False
1072
    resultCondFailed                = False
1073
    globalResultsList               = []
1074
    basisConstructionsCount         = 0
1075
    basisConstructionsFullTime      = 0
1076
    basisConstructionTime           = 0
1077
    reductionsCount                 = 0
1078
    reductionsFullTime              = 0
1079
    reductionTime                   = 0
1080
    resultantsComputationsCount     = 0
1081
    resultantsComputationsFullTime  = 0
1082
    resultantsComputationTime       = 0
1083
    rootsComputationsCount          = 0
1084
    rootsComputationsFullTime       = 0
1085
    rootsComputationTime            = 0
1086
    print
1087
    ## Global times are started here.
1088
    wallTimeStart                   = walltime()
1089
    cpuTimeStart                    = cputime()
1090
    ## Main loop.
1091
    while True:
1092
        if lb >= sdub:
1093
            print "Lower bound reached upper bound."
1094
            break
1095
        if iterCount == maxIter:
1096
            print "Reached maxIter. Aborting"
1097
            break
1098
        iterCount += 1
1099
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
1100
            "log2(numbers)." 
1101
        ### Compute a Sollya polynomial that will honor the Taylor condition.
1102
        prceSo = slz_compute_polynomial_and_interval(scaledfSo,
1103
                                                     degreeSo,
1104
                                                     lb,
1105
                                                     ub,
1106
                                                     polyApproxAccur)
1107
        ### Convert back the data into Sage space.                         
1108
        (floatP, floatPcv, intvl, ic, terr) = \
1109
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
1110
                                                 prceSo[1], prceSo[2], 
1111
                                                 prceSo[3]))
1112
        intvl = RRIF(intvl)
1113
        ## Clean-up Sollya stuff.
1114
        for elem in prceSo:
1115
            sollya_lib_clear_obj(elem)
1116
        #print  floatP, floatPcv, intvl, ic, terr
1117
        #print floatP
1118
        #print intvl.endpoints()[0].n(), \
1119
        #      ic.n(),
1120
        #intvl.endpoints()[1].n()
1121
        ### Check returned data.
1122
        #### Is approximation error OK?
1123
        if terr > polyApproxAccur:
1124
            exceptionErrorMess  = \
1125
                "Approximation failed - computed error:" + \
1126
                str(terr) + " - target error: "
1127
            exceptionErrorMess += \
1128
                str(polyApproxAccur) + ". Aborting!"
1129
            raise Exception(exceptionErrorMess)
1130
        #### Is lower bound OK?
1131
        if lb != intvl.endpoints()[0]:
1132
            exceptionErrorMess =  "Wrong lower bound:" + \
1133
                               str(lb) + ". Aborting!"
1134
            raise Exception(exceptionErrorMess)
1135
        #### Set upper bound.
1136
        if ub > intvl.endpoints()[1]:
1137
            ub = intvl.endpoints()[1]
1138
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
1139
            "log2(numbers)." 
1140
            taylCondFailedCount += 1
1141
        #### Is interval not degenerate?
1142
        if lb >= ub:
1143
            exceptionErrorMess = "Degenerate interval: " + \
1144
                                "lowerBound(" + str(lb) +\
1145
                                ")>= upperBound(" + str(ub) + \
1146
                                "). Aborting!"
1147
            raise Exception(exceptionErrorMess)
1148
        #### Is interval center ok?
1149
        if ic <= lb or ic >= ub:
1150
            exceptionErrorMess =  "Invalid interval center for " + \
1151
                                str(lb) + ',' + str(ic) + ',' +  \
1152
                                str(ub) + ". Aborting!"
1153
            raise Exception(exceptionErrorMess)
1154
        ##### Current interval width and reset future interval width.
1155
        bw = ub - lb
1156
        nbw = 0
1157
        icAsInt = int(ic * toIntegerFactor)
1158
        #### The following ratio is always >= 1. In case we may want to
1159
        #    enlarge the interval
1160
        curTaylErrRat = polyApproxAccur / terr
1161
        ### Make the  integral transformations.
1162
        #### Bounds and interval center.
1163
        intIc = int(ic * toIntegerFactor)
1164
        intLb = int(lb * toIntegerFactor) - intIc
1165
        intUb = int(ub * toIntegerFactor) - intIc
1166
        #
1167
        #### Polynomials
1168
        basisConstructionTime         = cputime()
1169
        ##### To a polynomial with rational coefficients with rational arguments
1170
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
1171
        ##### To a polynomial with rational coefficients with integer arguments
1172
        ratIntP = \
1173
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
1174
        #####  Ultimately a multivariate polynomial with integer coefficients  
1175
        #      with integer arguments.
1176
        coppersmithTuple = \
1177
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP, 
1178
                                                        precision, 
1179
                                                        targetHardnessToRound, 
1180
                                                        i, t)
1181
        #### Recover Coppersmith information.
1182
        intIntP = coppersmithTuple[0]
1183
        N = coppersmithTuple[1]
1184
        nAtAlpha = N^alpha
1185
        tBound = coppersmithTuple[2]
1186
        leastCommonMultiple = coppersmithTuple[3]
1187
        iBound = max(abs(intLb),abs(intUb))
1188
        basisConstructionsFullTime        += cputime(basisConstructionTime)
1189
        basisConstructionsCount           += 1
1190
        reductionTime                     = cputime()
1191
        #### Compute the reduced polynomials.
1192
        ccReducedPolynomialsList =  \
1193
                slz_compute_coppersmith_reduced_polynomials(intIntP, 
1194
                                                            alpha, 
1195
                                                            N, 
1196
                                                            iBound, 
1197
                                                            tBound)
1198
        if ccReducedPolynomialsList is None:
1199
            raise Exception("Reduction failed.")
1200
        reductionsFullTime    += cputime(reductionTime)
1201
        reductionsCount       += 1
1202
        if len(ccReducedPolynomialsList) < 2:
1203
            print "Nothing to form resultants with."
1204
            print
1205
            coppCondFailedCount += 1
1206
            coppCondFailed = True
1207
            ##### Apply a different shrink factor according to 
1208
            #  the number of compliant polynomials.
1209
            if len(ccReducedPolynomialsList) == 0:
1210
                ub = lb + bw * noCoppersmithIntervalShrink
1211
            else: # At least one compliant polynomial.
1212
                ub = lb + bw * oneCoppersmithIntervalShrink
1213
            if ub > sdub:
1214
                ub = sdub
1215
            if lb == ub:
1216
                raise Exception("Cant shrink interval \
1217
                anymore to get Coppersmith condition.")
1218
            nbw = 0
1219
            continue
1220
        #### We have at least two polynomials.
1221
        #    Let us try to compute resultants.
1222
        #    For each resultant computed, go for the solutions.
1223
        ##### Build the pairs list.
1224
        polyPairsList           = []
1225
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
1226
            for polyInnerIndex in xrange(polyOuterIndex+1, 
1227
                                         len(ccReducedPolynomialsList)):
1228
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
1229
                                      ccReducedPolynomialsList[polyInnerIndex]))
1230
        #### Actual root search.
1231
        rootsSet            = set()
1232
        hasNonNullResultant = False
1233
        for polyPair in polyPairsList:
1234
            if hasNonNullResultant:
1235
                break
1236
            resultantsComputationTime   = cputime()
1237
            currentResultantI = \
1238
                slz_resultant(polyPair[0],
1239
                              polyPair[1],
1240
                              t)
1241
            resultantsComputationsCount    += 1
1242
            if currentResultantI is None:
1243
                resultantsComputationsFullTime +=  \
1244
                    cputime(resultantsComputationTime)
1245
                print "Nul resultant"
1246
                continue # Next polyPair.
1247
            currentResultantT = \
1248
                slz_resultant(polyPair[0],
1249
                              polyPair[1],
1250
                              i)
1251
            resultantsComputationsFullTime += cputime(resultantsComputationTime)
1252
            resultantsComputationsCount    += 1
1253
            if currentResultantT is None:                    
1254
                print "Nul resultant"
1255
                continue # Next polyPair.
1256
            else:
1257
                hasNonNullResultant = True
1258
            #### We have a non null resultants pair. From now on, whatever the
1259
            #    root search yields, no extra root search is necessary.
1260
            #### A constant resultant leads to no root. Root search is done.
1261
            if currentResultantI.degree() < 1:
1262
                print "Resultant is constant:", currentResultantI
1263
                break # Next polyPair and should break.
1264
            if currentResultantT.degree() < 1:
1265
                print "Resultant is constant:", currentResultantT
1266
                break # Next polyPair and should break.
1267
            #### Actual roots computation.
1268
            rootsComputationTime       = cputime()
1269
            ##### Compute i roots
1270
            iRootsList = Zi(currentResultantI).roots()
1271
            rootsComputationsCount      +=  1
1272
            if len(iRootsList) == 0:
1273
                rootsComputationsFullTime   =   cputime(rootsComputationTime)
1274
                print "No roots in \"i\"."
1275
                break # No roots in i.
1276
            tRootsList = Zt(currentResultantT).roots()
1277
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
1278
            rootsComputationsCount      +=  1
1279
            if len(tRootsList) == 0:
1280
                print "No roots in \"t\"."
1281
                break # No roots in i.
1282
            ##### For each iRoot, get a tRoot and check against the polynomials.
1283
            for iRoot in iRootsList:
1284
                ####### Roots returned by roots() are (value, multiplicity) 
1285
                #       tuples.
1286
                #print "iRoot:", iRoot
1287
                for tRoot in tRootsList:
1288
                ###### Use the tRoot against each polynomial, alternatively.
1289
                    if polyPair[0](iRoot[0],tRoot[0]) != 0:
1290
                        continue
1291
                    if polyPair[1](iRoot[0],tRoot[0]) != 0:
1292
                        continue
1293
                    rootsSet.add((iRoot[0], tRoot[0]))
1294
            # End of roots computation.
1295
        # End loop for polyPair in polyParsList.  Will break at next iteration.
1296
        # since a non null resultant was found.
1297
        #### Prepare for results for the current interval..
1298
        intervalResultsList = []
1299
        intervalResultsList.append((lb, ub))
1300
        #### Check roots.
1301
        rootsResultsList = []
1302
        for root in rootsSet:
1303
            specificRootResultsList = []
1304
            failingBounds = []
1305
            intIntPdivN = intIntP(root[0], root[1]) / N
1306
            if int(intIntPdivN) != intIntPdivN:
1307
                continue # Next root
1308
            # Root qualifies for modular equation, test it for hardness to round.
1309
            hardToRoundCaseAsFloat = RRR((icAsInt + root[0]) / toIntegerFactor)
1310
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
1311
            #print scalingFunction
1312
            scaledHardToRoundCaseAsFloat = \
1313
                scalingFunction(hardToRoundCaseAsFloat) 
1314
            print "Candidate HTRNc at x =", \
1315
                scaledHardToRoundCaseAsFloat.n().str(base=2),
1316
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
1317
                           function,
1318
                           2^-(targetHardnessToRound),
1319
                           RRR):
1320
                print hardToRoundCaseAsFloat, "is HTRN case."
1321
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
1322
                    print "Found in interval."
1323
                else:
1324
                    print "Found out of interval."
1325
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
1326
                # Check the root is in the bounds
1327
                if abs(root[0]) > iBound or abs(root[1]) > tBound:
1328
                    print "Root", root, "is out of bounds for modular equation."
1329
                    if abs(root[0]) > iBound:
1330
                        print "root[0]:", root[0]
1331
                        print "i bound:", iBound
1332
                        failingBounds.append('i')
1333
                        failingBounds.append(root[0])
1334
                        failingBounds.append(iBound)
1335
                    if abs(root[1]) > tBound:
1336
                        print "root[1]:", root[1]
1337
                        print "t bound:", tBound
1338
                        failingBounds.append('t')
1339
                        failingBounds.append(root[1])
1340
                        failingBounds.append(tBound)
1341
                if len(failingBounds) > 0:
1342
                    specificRootResultsList.append(failingBounds)
1343
            else: # From slz_is_htrn...
1344
                print "is not an HTRN case."
1345
            if len(specificRootResultsList) > 0:
1346
                rootsResultsList.append(specificRootResultsList)
1347
        if len(rootsResultsList) > 0:
1348
            intervalResultsList.append(rootsResultsList)
1349
        ### Check if a non null resultant was found. If not shrink the interval.
1350
        if not hasNonNullResultant:
1351
            print "Only null resultants for this reduction, shrinking interval."
1352
            resultCondFailed      =  True
1353
            resultCondFailedCount += 1
1354
            ### Shrink interval for next iteration.
1355
            ub = lb + bw * onlyNullResultantsShrink
1356
            if ub > sdub:
1357
                ub = sdub
1358
            nbw = 0
1359
            continue
1360
        #### An intervalResultsList has at least the bounds.
1361
        globalResultsList.append(intervalResultsList)   
1362
        #### Compute an incremented width for next upper bound, only
1363
        #    if not Coppersmith condition nor resultant condition
1364
        #    failed at the previous run. 
1365
        if not coppCondFailed and not resultCondFailed:
1366
            nbw = noErrorIntervalStretch * bw
1367
        else:
1368
            nbw = bw
1369
        ##### Reset the failure flags. They will be raised
1370
        #     again if needed.
1371
        coppCondFailed   = False
1372
        resultCondFailed = False
1373
        #### For next iteration (at end of loop)
1374
        #print "nbw:", nbw
1375
        lb  = ub
1376
        ub += nbw     
1377
        if ub > sdub:
1378
            ub = sdub
1379
        print
1380
    # End while True
1381
    ## Main loop just ended.
1382
    globalWallTime = walltime(wallTimeStart)
1383
    globalCpuTime  = cputime(cpuTimeStart)
1384
    ## Output results
1385
    print ; print "Intervals and HTRNs" ; print
1386
    for intervalResultsList in globalResultsList:
1387
        print "[", intervalResultsList[0][0], ",",intervalResultsList[0][1], "]",
1388
        if len(intervalResultsList) > 1:
1389
            rootsResultsList = intervalResultsList[1]
1390
            for specificRootResultsList in rootsResultsList:
1391
                print "\t", specificRootResultsList[0],
1392
                if len(specificRootResultsList) > 1:
1393
                    print specificRootResultsList[1],
1394
        print ; print
1395
    #print globalResultsList
1396
    #
1397
    print "Timers and counters"
1398
    print
1399
    print "Number of iterations:", iterCount
1400
    print "Taylor condition failures:", taylCondFailedCount
1401
    print "Coppersmith condition failures:", coppCondFailedCount
1402
    print "Resultant condition failures:", resultCondFailedCount
1403
    print "Iterations count: ", iterCount
1404
    print "Number of intervals:", len(globalResultsList)
1405
    print "Number of basis constructions:", basisConstructionsCount 
1406
    print "Total CPU time spent in basis constructions:", \
1407
        basisConstructionsFullTime
1408
    if basisConstructionsCount != 0:
1409
        print "Average basis construction CPU time:", \
1410
            basisConstructionsFullTime/basisConstructionsCount
1411
    print "Number of reductions:", reductionsCount
1412
    print "Total CPU time spent in reductions:", reductionsFullTime
1413
    if reductionsCount != 0:
1414
        print "Average reduction CPU time:", \
1415
            reductionsFullTime/reductionsCount
1416
    print "Number of resultants computation rounds:", \
1417
        resultantsComputationsCount
1418
    print "Total CPU time spent in resultants computation rounds:", \
1419
        resultantsComputationsFullTime
1420
    if resultantsComputationsCount != 0:
1421
        print "Average resultants computation round CPU time:", \
1422
            resultantsComputationsFullTime/resultantsComputationsCount
1423
    print "Number of root finding rounds:", rootsComputationsCount
1424
    print "Total CPU time spent in roots finding rounds:", \
1425
        rootsComputationsFullTime
1426
    if rootsComputationsCount != 0:
1427
        print "Average roots finding round CPU time:", \
1428
            rootsComputationsFullTime/rootsComputationsCount
1429
    print "Global Wall time:", globalWallTime
1430
    print "Global CPU time:", globalCpuTime
1431
    ## Output counters
1432
# End srs_runSLZ-v03
1433

  
1434
def srs_compute_lattice_volume(inputFunction,
1435
                    inputLowerBound,
1436
                    inputUpperBound,
1437
                    alpha,
1438
                    degree,
1439
                    precision,
1440
                    emin,
1441
                    emax,
1442
                    targetHardnessToRound,
1443
                    debug = False):
1444
    """
1445
    Changes from V2:
1446
        Root search is changed:
1447
            - we compute the resultants in i and in t;
1448
            - we compute the roots set of each of these resultants;
1449
            - we combine all the possible pairs between the two sets;
1450
            - we check these pairs in polynomials for correctness.
1451
    Changes from V1: 
1452
        1- check for roots as soon as a resultant is computed;
1453
        2- once a non null resultant is found, check for roots;
1454
        3- constant resultant == no root.
1455
    """
1456

  
1457
    if debug:
1458
        print "Function                :", inputFunction
1459
        print "Lower bound             :", inputLowerBound
1460
        print "Upper bounds            :", inputUpperBound
1461
        print "Alpha                   :", alpha
1462
        print "Degree                  :", degree
1463
        print "Precision               :", precision
1464
        print "Emin                    :", emin
1465
        print "Emax                    :", emax
1466
        print "Target hardness-to-round:", targetHardnessToRound
1467
        print
1468
    ## Important constants.
1469
    ### Stretch the interval if no error happens.
1470
    noErrorIntervalStretch = 1 + 2^(-5)
1471
    ### If no vector validates the Coppersmith condition, shrink the interval
1472
    #   by the following factor.
1473
    noCoppersmithIntervalShrink = 1/2
1474
    ### If only (or at least) one vector validates the Coppersmith condition, 
1475
    #   shrink the interval by the following factor.
1476
    oneCoppersmithIntervalShrink = 3/4
1477
    #### If only null resultants are found, shrink the interval by the 
1478
    #    following factor.
1479
    onlyNullResultantsShrink     = 3/4
1480
    ## Structures.
1481
    RRR         = RealField(precision)
1482
    RRIF        = RealIntervalField(precision)
1483
    ## Converting input bound into the "right" field.
1484
    lowerBound = RRR(inputLowerBound)
1485
    upperBound = RRR(inputUpperBound)
1486
    ## Before going any further, check domain and image binade conditions.
1487
    print inputFunction(1).n()
1488
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
1489
    if output is None:
1490
        print "Invalid domain/image binades. Domain:",\
1491
        lowerBound, upperBound, "Images:", \
1492
        inputFunction(lowerBound), inputFunction(upperBound)
1493
        raise Exception("Invalid domain/image binades.")
1494
    lb = output[0] ; ub = output[1]
1495
    if lb != lowerBound or ub != upperBound:
1496
        print "lb:", lb, " - ub:", ub
1497
        print "Invalid domain/image binades. Domain:",\
1498
        lowerBound, upperBound, "Images:", \
1499
        inputFunction(lowerBound), inputFunction(upperBound)
1500
        raise Exception("Invalid domain/image binades.")
1501
    #
1502
    ## Progam initialization
1503
    ### Approximation polynomial accuracy and hardness to round.
1504
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
1505
    polyTargetHardnessToRound = targetHardnessToRound + 1
1506
    ### Significand to integer conversion ratio.
1507
    toIntegerFactor           = 2^(precision-1)
1508
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
1509
    ### Variables and rings for polynomials and root searching.
1510
    i=var('i')
1511
    t=var('t')
1512
    inputFunctionVariable = inputFunction.variables()[0]
1513
    function = inputFunction.subs({inputFunctionVariable:i})
1514
    #  Polynomial Rings over the integers, for root finding.
1515
    Zi = ZZ[i]
1516
    Zt = ZZ[t]
1517
    Zit = ZZ[i,t]
1518
    ## Number of iterations limit.
1519
    maxIter = 100000
1520
    #
1521
    ## Compute the scaled function and the degree, in their Sollya version 
1522
    #  once for all.
1523
    (scaledf, sdlb, sdub, silb, siub) = \
1524
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
1525
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
1526
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
1527
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
1528
    #
1529
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
1530
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
1531
    (unscalingFunction, scalingFunction) = \
1532
        slz_interval_scaling_expression(domainBoundsInterval, i)
1533
    #print scalingFunction, unscalingFunction
1534
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
1535
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
1536
    if internalSollyaPrec < 192:
1537
        internalSollyaPrec = 192
1538
    pobyso_set_prec_sa_so(internalSollyaPrec)
1539
    print "Sollya internal precision:", internalSollyaPrec
1540
    ## Some variables.
1541
    ### General variables
1542
    lb                  = sdlb
1543
    ub                  = sdub
1544
    nbw                 = 0
1545
    intervalUlp         = ub.ulp()
1546
    #### Will be set by slz_interval_and_polynomila_to_sage.
1547
    ic                  = 0 
1548
    icAsInt             = 0    # Set from ic.
1549
    solutionsSet        = set()
1550
    tsErrorWidth        = []
1551
    csErrorVectors      = []
1552
    csVectorsResultants = []
1553
    floatP              = 0  # Taylor polynomial.
1554
    floatPcv            = 0  # Ditto with variable change.
1555
    intvl               = "" # Taylor interval
1556
    terr                = 0  # Taylor error.
1557
    iterCount = 0
1558
    htrnSet = set()
1559
    ### Timers and counters.
1560
    wallTimeStart                   = 0
1561
    cpuTimeStart                    = 0
1562
    taylCondFailedCount             = 0
1563
    coppCondFailedCount             = 0
1564
    resultCondFailedCount           = 0
1565
    coppCondFailed                  = False
1566
    resultCondFailed                = False
1567
    globalResultsList               = []
1568
    basisConstructionsCount         = 0
1569
    basisConstructionsFullTime      = 0
1570
    basisConstructionTime           = 0
1571
    reductionsCount                 = 0
1572
    reductionsFullTime              = 0
1573
    reductionTime                   = 0
1574
    resultantsComputationsCount     = 0
1575
    resultantsComputationsFullTime  = 0
1576
    resultantsComputationTime       = 0
1577
    rootsComputationsCount          = 0
1578
    rootsComputationsFullTime       = 0
1579
    rootsComputationTime            = 0
1580
    print
1581
    ## Global times are started here.
1582
    wallTimeStart                   = walltime()
1583
    cpuTimeStart                    = cputime()
1584
    ## Main loop.
1585
    while True:
1586
        if lb >= sdub:
1587
            print "Lower bound reached upper bound."
1588
            break
1589
        if iterCount == maxIter:
1590
            print "Reached maxIter. Aborting"
1591
            break
1592
        iterCount += 1
1593
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
1594
            "log2(numbers)." 
1595
        ### Compute a Sollya polynomial that will honor the Taylor condition.
1596
        prceSo = slz_compute_polynomial_and_interval(scaledfSo,
1597
                                                     degreeSo,
1598
                                                     lb,
1599
                                                     ub,
1600
                                                     polyApproxAccur)
1601
        ### Convert back the data into Sage space.                         
1602
        (floatP, floatPcv, intvl, ic, terr) = \
1603
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
1604
                                                 prceSo[1], prceSo[2], 
1605
                                                 prceSo[3]))
1606
        intvl = RRIF(intvl)
1607
        ## Clean-up Sollya stuff.
1608
        for elem in prceSo:
1609
            sollya_lib_clear_obj(elem)
1610
        #print  floatP, floatPcv, intvl, ic, terr
1611
        #print floatP
1612
        #print intvl.endpoints()[0].n(), \
1613
        #      ic.n(),
1614
        #intvl.endpoints()[1].n()
1615
        ### Check returned data.
1616
        #### Is approximation error OK?
1617
        if terr > polyApproxAccur:
1618
            exceptionErrorMess  = \
1619
                "Approximation failed - computed error:" + \
1620
                str(terr) + " - target error: "
1621
            exceptionErrorMess += \
1622
                str(polyApproxAccur) + ". Aborting!"
1623
            raise Exception(exceptionErrorMess)
1624
        #### Is lower bound OK?
1625
        if lb != intvl.endpoints()[0]:
1626
            exceptionErrorMess =  "Wrong lower bound:" + \
1627
                               str(lb) + ". Aborting!"
1628
            raise Exception(exceptionErrorMess)
1629
        #### Set upper bound.
1630
        if ub > intvl.endpoints()[1]:
1631
            ub = intvl.endpoints()[1]
1632
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
1633
            "log2(numbers)." 
1634
            taylCondFailedCount += 1
1635
        #### Is interval not degenerate?
1636
        if lb >= ub:
1637
            exceptionErrorMess = "Degenerate interval: " + \
1638
                                "lowerBound(" + str(lb) +\
1639
                                ")>= upperBound(" + str(ub) + \
1640
                                "). Aborting!"
1641
            raise Exception(exceptionErrorMess)
1642
        #### Is interval center ok?
1643
        if ic <= lb or ic >= ub:
1644
            exceptionErrorMess =  "Invalid interval center for " + \
1645
                                str(lb) + ',' + str(ic) + ',' +  \
1646
                                str(ub) + ". Aborting!"
1647
            raise Exception(exceptionErrorMess)
1648
        ##### Current interval width and reset future interval width.
1649
        bw = ub - lb
1650
        nbw = 0
1651
        icAsInt = int(ic * toIntegerFactor)
1652
        #### The following ratio is always >= 1. In case we may want to
1653
        #    enlarge the interval
1654
        curTaylErrRat = polyApproxAccur / terr
1655
        ### Make the  integral transformations.
1656
        #### Bounds and interval center.
1657
        intIc = int(ic * toIntegerFactor)
1658
        intLb = int(lb * toIntegerFactor) - intIc
1659
        intUb = int(ub * toIntegerFactor) - intIc
1660
        #
1661
        #### Polynomials
1662
        basisConstructionTime         = cputime()
1663
        ##### To a polynomial with rational coefficients with rational arguments
1664
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
1665
        ##### To a polynomial with rational coefficients with integer arguments
1666
        ratIntP = \
1667
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
1668
        #####  Ultimately a multivariate polynomial with integer coefficients  
1669
        #      with integer arguments.
1670
        coppersmithTuple = \
1671
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP, 
1672
                                                        precision, 
1673
                                                        targetHardnessToRound, 
1674
                                                        i, t)
1675
        #### Recover Coppersmith information.
1676
        intIntP = coppersmithTuple[0]
1677
        N = coppersmithTuple[1]
1678
        nAtAlpha = N^alpha
1679
        tBound = coppersmithTuple[2]
1680
        leastCommonMultiple = coppersmithTuple[3]
1681
        iBound = max(abs(intLb),abs(intUb))
1682
        basisConstructionsFullTime        += cputime(basisConstructionTime)
1683
        basisConstructionsCount           += 1
1684
        reductionTime                     = cputime()
1685
        #### Compute the reduced polynomials.
1686
        ccReducedPolynomialsList =  \
1687
            slz_compute_coppersmith_reduced_polynomials_with_lattice_volume(intIntP, 
1688
                                                        alpha, 
1689
                                                        N, 
1690
                                                        iBound, 
1691
                                                        tBound)
1692
        if ccReducedPolynomialsList is None:
1693
            raise Exception("Reduction failed.")
1694
        reductionsFullTime    += cputime(reductionTime)
1695
        reductionsCount       += 1
1696
        if len(ccReducedPolynomialsList) < 2:
1697
            print "Nothing to form resultants with."
1698
            print
1699
            coppCondFailedCount += 1
1700
            coppCondFailed = True
1701
            ##### Apply a different shrink factor according to 
1702
            #  the number of compliant polynomials.
1703
            if len(ccReducedPolynomialsList) == 0:
1704
                ub = lb + bw * noCoppersmithIntervalShrink
1705
            else: # At least one compliant polynomial.
1706
                ub = lb + bw * oneCoppersmithIntervalShrink
1707
            if ub > sdub:
1708
                ub = sdub
1709
            if lb == ub:
1710
                raise Exception("Cant shrink interval \
1711
                anymore to get Coppersmith condition.")
1712
            nbw = 0
1713
            continue
1714
        #### We have at least two polynomials.
1715
        #    Let us try to compute resultants.
1716
        #    For each resultant computed, go for the solutions.
1717
        ##### Build the pairs list.
1718
        polyPairsList           = []
1719
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
1720
            for polyInnerIndex in xrange(polyOuterIndex+1, 
1721
                                         len(ccReducedPolynomialsList)):
1722
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
1723
                                      ccReducedPolynomialsList[polyInnerIndex]))
1724
        #### Actual root search.
1725
        rootsSet            = set()
1726
        hasNonNullResultant = False
1727
        for polyPair in polyPairsList:
1728
            if hasNonNullResultant:
1729
                break
1730
            resultantsComputationTime   = cputime()
1731
            currentResultantI = \
1732
                slz_resultant(polyPair[0],
1733
                              polyPair[1],
1734
                              t)
1735
            resultantsComputationsCount    += 1
1736
            if currentResultantI is None:
1737
                resultantsComputationsFullTime +=  \
1738
                    cputime(resultantsComputationTime)
1739
                print "Nul resultant"
1740
                continue # Next polyPair.
1741
            currentResultantT = \
1742
                slz_resultant(polyPair[0],
1743
                              polyPair[1],
1744
                              i)
1745
            resultantsComputationsFullTime += cputime(resultantsComputationTime)
1746
            resultantsComputationsCount    += 1
1747
            if currentResultantT is None:                    
1748
                print "Nul resultant"
1749
                continue # Next polyPair.
1750
            else:
1751
                hasNonNullResultant = True
1752
            #### We have a non null resultants pair. From now on, whatever the
1753
            #    root search yields, no extra root search is necessary.
1754
            #### A constant resultant leads to no root. Root search is done.
1755
            if currentResultantI.degree() < 1:
1756
                print "Resultant is constant:", currentResultantI
1757
                break # Next polyPair and should break.
1758
            if currentResultantT.degree() < 1:
1759
                print "Resultant is constant:", currentResultantT
1760
                break # Next polyPair and should break.
1761
            #### Actual roots computation.
1762
            rootsComputationTime       = cputime()
1763
            ##### Compute i roots
1764
            iRootsList = Zi(currentResultantI).roots()
1765
            rootsComputationsCount      +=  1
1766
            if len(iRootsList) == 0:
1767
                rootsComputationsFullTime   =   cputime(rootsComputationTime)
1768
                print "No roots in \"i\"."
1769
                break # No roots in i.
1770
            tRootsList = Zt(currentResultantT).roots()
1771
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
1772
            rootsComputationsCount      +=  1
1773
            if len(tRootsList) == 0:
1774
                print "No roots in \"t\"."
1775
                break # No roots in i.
1776
            ##### For each iRoot, get a tRoot and check against the polynomials.
1777
            for iRoot in iRootsList:
1778
                ####### Roots returned by roots() are (value, multiplicity) 
1779
                #       tuples.
1780
                #print "iRoot:", iRoot
1781
                for tRoot in tRootsList:
1782
                ###### Use the tRoot against each polynomial, alternatively.
1783
                    if polyPair[0](iRoot[0],tRoot[0]) != 0:
1784
                        continue
1785
                    if polyPair[1](iRoot[0],tRoot[0]) != 0:
1786
                        continue
1787
                    rootsSet.add((iRoot[0], tRoot[0]))
1788
            # End of roots computation.
1789
        # End loop for polyPair in polyParsList.  Will break at next iteration.
1790
        # since a non null resultant was found.
1791
        #### Prepare for results for the current interval..
1792
        intervalResultsList = []
1793
        intervalResultsList.append((lb, ub))
1794
        #### Check roots.
1795
        rootsResultsList = []
1796
        for root in rootsSet:
1797
            specificRootResultsList = []
1798
            failingBounds = []
1799
            intIntPdivN = intIntP(root[0], root[1]) / N
1800
            if int(intIntPdivN) != intIntPdivN:
1801
                continue # Next root
1802
            # Root qualifies for modular equation, test it for hardness to round.
1803
            hardToRoundCaseAsFloat = RRR((icAsInt + root[0]) / toIntegerFactor)
1804
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
1805
            #print scalingFunction
1806
            scaledHardToRoundCaseAsFloat = \
1807
                scalingFunction(hardToRoundCaseAsFloat) 
1808
            print "Candidate HTRNc at x =", \
1809
                scaledHardToRoundCaseAsFloat.n().str(base=2),
1810
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
1811
                           function,
1812
                           2^-(targetHardnessToRound),
1813
                           RRR):
1814
                print hardToRoundCaseAsFloat, "is HTRN case."
1815
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
1816
                    print "Found in interval."
1817
                else:
1818
                    print "Found out of interval."
1819
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
1820
                # Check the root is in the bounds
1821
                if abs(root[0]) > iBound or abs(root[1]) > tBound:
1822
                    print "Root", root, "is out of bounds for modular equation."
1823
                    if abs(root[0]) > iBound:
1824
                        print "root[0]:", root[0]
1825
                        print "i bound:", iBound
1826
                        failingBounds.append('i')
1827
                        failingBounds.append(root[0])
1828
                        failingBounds.append(iBound)
1829
                    if abs(root[1]) > tBound:
1830
                        print "root[1]:", root[1]
1831
                        print "t bound:", tBound
1832
                        failingBounds.append('t')
1833
                        failingBounds.append(root[1])
1834
                        failingBounds.append(tBound)
1835
                if len(failingBounds) > 0:
1836
                    specificRootResultsList.append(failingBounds)
1837
            else: # From slz_is_htrn...
1838
                print "is not an HTRN case."
1839
            if len(specificRootResultsList) > 0:
1840
                rootsResultsList.append(specificRootResultsList)
1841
        if len(rootsResultsList) > 0:
1842
            intervalResultsList.append(rootsResultsList)
1843
        ### Check if a non null resultant was found. If not shrink the interval.
1844
        if not hasNonNullResultant:
1845
            print "Only null resultants for this reduction, shrinking interval."
1846
            resultCondFailed      =  True
1847
            resultCondFailedCount += 1
1848
            ### Shrink interval for next iteration.
1849
            ub = lb + bw * onlyNullResultantsShrink
1850
            if ub > sdub:
1851
                ub = sdub
1852
            nbw = 0
1853
            continue
1854
        #### An intervalResultsList has at least the bounds.
1855
        globalResultsList.append(intervalResultsList)   
1856
        #### Compute an incremented width for next upper bound, only
1857
        #    if not Coppersmith condition nor resultant condition
1858
        #    failed at the previous run. 
1859
        if not coppCondFailed and not resultCondFailed:
1860
            nbw = noErrorIntervalStretch * bw
1861
        else:
1862
            nbw = bw
1863
        ##### Reset the failure flags. They will be raised
1864
        #     again if needed.
1865
        coppCondFailed   = False
1866
        resultCondFailed = False
1867
        #### For next iteration (at end of loop)
1868
        #print "nbw:", nbw
1869
        lb  = ub
1870
        ub += nbw     
1871
        if ub > sdub:
1872
            ub = sdub
1873
        print
1874
    # End while True
1875
    ## Main loop just ended.
1876
    globalWallTime = walltime(wallTimeStart)
1877
    globalCpuTime  = cputime(cpuTimeStart)
1878
    ## Output results
1879
    print ; print "Intervals and HTRNs" ; print
1880
    for intervalResultsList in globalResultsList:
1881
        print "[", intervalResultsList[0][0], ",",intervalResultsList[0][1], "]",
1882
        if len(intervalResultsList) > 1:
1883
            rootsResultsList = intervalResultsList[1]
1884
            for specificRootResultsList in rootsResultsList:
1885
                print "\t", specificRootResultsList[0],
1886
                if len(specificRootResultsList) > 1:
1887
                    print specificRootResultsList[1],
1888
        print ; print
1889
    #print globalResultsList
1890
    #
1891
    print "Timers and counters"
1892
    print
1893
    print "Number of iterations:", iterCount
1894
    print "Taylor condition failures:", taylCondFailedCount
1895
    print "Coppersmith condition failures:", coppCondFailedCount
1896
    print "Resultant condition failures:", resultCondFailedCount
1897
    print "Iterations count: ", iterCount
1898
    print "Number of intervals:", len(globalResultsList)
1899
    print "Number of basis constructions:", basisConstructionsCount 
1900
    print "Total CPU time spent in basis constructions:", \
1901
        basisConstructionsFullTime
1902
    if basisConstructionsCount != 0:
1903
        print "Average basis construction CPU time:", \
1904
            basisConstructionsFullTime/basisConstructionsCount
1905
    print "Number of reductions:", reductionsCount
1906
    print "Total CPU time spent in reductions:", reductionsFullTime
1907
    if reductionsCount != 0:
1908
        print "Average reduction CPU time:", \
1909
            reductionsFullTime/reductionsCount
1910
    print "Number of resultants computation rounds:", \
1911
        resultantsComputationsCount
1912
    print "Total CPU time spent in resultants computation rounds:", \
1913
        resultantsComputationsFullTime
1914
    if resultantsComputationsCount != 0:
1915
        print "Average resultants computation round CPU time:", \
1916
            resultantsComputationsFullTime/resultantsComputationsCount
1917
    print "Number of root finding rounds:", rootsComputationsCount
1918
    print "Total CPU time spent in roots finding rounds:", \
1919
        rootsComputationsFullTime
1920
    if rootsComputationsCount != 0:
1921
        print "Average roots finding round CPU time:", \
1922
            rootsComputationsFullTime/rootsComputationsCount
1923
    print "Global Wall time:", globalWallTime
1924
    print "Global CPU time:", globalCpuTime
1925
    ## Output counters
1926
# End srs_compute_lattice_volume
940 1927
 

Formats disponibles : Unified diff