Statistiques
| Révision :

root / pobysoPythonSage / src / pobyso.py @ 37

Historique | Voir | Annoter | Télécharger (16,32 ko)

1
"""
2
Actual functions to use in Sage
3
ST 2012-11-13
4

5
Command line syntax:
6
  use from Sage (via the "load" or the "attach" commands)
7

8
NOTES:
9
Reported errors in Eclipse come from the calls to
10
the Sollya library
11

12
ToDo (among other things): 
13
 -memory management.
14
"""
15
from ctypes import *
16
import re
17
from sage.symbolic.expression_conversions import polynomial
18

    
19
(SOLLYA_BASE_FUNC_ABS,
20
SOLLYA_BASE_FUNC_ACOS,
21
    SOLLYA_BASE_FUNC_ACOSH,
22
    SOLLYA_BASE_FUNC_ADD,
23
    SOLLYA_BASE_FUNC_ASIN,
24
    SOLLYA_BASE_FUNC_ASINH,
25
    SOLLYA_BASE_FUNC_ATAN,
26
    SOLLYA_BASE_FUNC_ATANH,
27
    SOLLYA_BASE_FUNC_CEIL,
28
    SOLLYA_BASE_FUNC_CONSTANT,
29
    SOLLYA_BASE_FUNC_COS,
30
    SOLLYA_BASE_FUNC_COSH,
31
    SOLLYA_BASE_FUNC_DIV,
32
    SOLLYA_BASE_FUNC_DOUBLE,
33
    SOLLYA_BASE_FUNC_DOUBLEDOUBLE,
34
    SOLLYA_BASE_FUNC_DOUBLEEXTENDED,
35
    SOLLYA_BASE_FUNC_ERF,
36
    SOLLYA_BASE_FUNC_ERFC,
37
    SOLLYA_BASE_FUNC_EXP,
38
    SOLLYA_BASE_FUNC_EXP_M1,
39
    SOLLYA_BASE_FUNC_FLOOR,
40
    SOLLYA_BASE_FUNC_FREE_VARIABLE,
41
    SOLLYA_BASE_FUNC_HALFPRECISION,
42
    SOLLYA_BASE_FUNC_LIBRARYCONSTANT,
43
    SOLLYA_BASE_FUNC_LIBRARYFUNCTION,
44
    SOLLYA_BASE_FUNC_LOG,
45
    SOLLYA_BASE_FUNC_LOG_10,
46
    SOLLYA_BASE_FUNC_LOG_1P,
47
    SOLLYA_BASE_FUNC_LOG_2,
48
    SOLLYA_BASE_FUNC_MUL,
49
    SOLLYA_BASE_FUNC_NEARESTINT,
50
    SOLLYA_BASE_FUNC_NEG,
51
    SOLLYA_BASE_FUNC_PI,
52
    SOLLYA_BASE_FUNC_POW,
53
    SOLLYA_BASE_FUNC_PROCEDUREFUNCTION,
54
    SOLLYA_BASE_FUNC_QUAD,
55
    SOLLYA_BASE_FUNC_SIN,
56
    SOLLYA_BASE_FUNC_SINGLE,
57
    SOLLYA_BASE_FUNC_SINH,
58
    SOLLYA_BASE_FUNC_SQRT,
59
    SOLLYA_BASE_FUNC_SUB,
60
    SOLLYA_BASE_FUNC_TAN,
61
    SOLLYA_BASE_FUNC_TANH,
62
SOLLYA_BASE_FUNC_TRIPLEDOUBLE) = map(int,xrange(44))
63
print "First constant - SOLLYA_BASE_FUNC_ABS: ", SOLLYA_BASE_FUNC_ABS
64
print "Last constant  - SOLLYA_BASE_FUNC_TRIPLEDOUBLE: ", SOLLYA_BASE_FUNC_TRIPLEDOUBLE
65

    
66
pobyso_max_arity = 9
67

    
68
def pobyso_autoprint(arg):
69
    sollya_lib_autoprint(arg,None)
70

    
71
def pobyso_cmp(rnArg, soCte):
72
    precisionOfCte = c_int(0)
73
    # From the Sollya constant, create a local Sage RealNumber.
74
    sollya_lib_get_prec_of_constant(precisionOfCte, soCte) 
75
    #print "Precision of constant: ", precisionOfCte
76
    RRRR = RealField(precisionOfCte.value)
77
    rnLocal = RRRR(0)
78
    sollya_lib_get_constant(get_rn_value(rnLocal), soCte)
79
    #print "rnDummy: ", rnDummy
80
    # Compare the local Sage RealNumber with rnArg.
81
    return(cmp_rn_value(rnArg, rnLocal))
82

    
83
def pobyso_constant(rnArg):
84
    return (sollya_lib_constant(get_rn_value(rnArg)))
85
    
86
def pobyso_constant_1():
87
    return(pobyso_constant_from_int(1))
88

    
89
def pobyso_constant_from_int(anInt):
90
    return(sollya_lib_constant_from_int(int(anInt)))
91

    
92
# Numeric Sollya function codes -> Sage mathematical function names
93
def pobyso_function_type_as_string(funcType):
94
    if funcType == SOLLYA_BASE_FUNC_ABS:
95
        return "abs"
96
    elif funcType == SOLLYA_BASE_FUNC_ACOS:
97
        return "arccos"
98
    elif funcType == SOLLYA_BASE_FUNC_ACOSH:
99
        return "arccosh"
100
    elif funcType == SOLLYA_BASE_FUNC_ADD:
101
        return "+"
102
    elif funcType == SOLLYA_BASE_FUNC_ASIN:
103
        return "arcsin"
104
    elif funcType == SOLLYA_BASE_FUNC_ASINH:
105
        return "arcsinh"
106
    elif funcType == SOLLYA_BASE_FUNC_ATAN:
107
        return "arctan"
108
    elif funcType == SOLLYA_BASE_FUNC_ATANH:
109
        return "arctanh"
110
    elif funcType == SOLLYA_BASE_FUNC_CEIL:
111
        return "ceil"
112
    elif funcType == SOLLYA_BASE_FUNC_CONSTANT:
113
        return "cte"
114
    elif funcType == SOLLYA_BASE_FUNC_COS:
115
        return "cos"
116
    elif funcType == SOLLYA_BASE_FUNC_COSH:
117
        return "cosh"
118
    elif funcType == SOLLYA_BASE_FUNC_DIV:
119
        return "/"
120
    elif funcType == SOLLYA_BASE_FUNC_DOUBLE:
121
        return "double"
122
    elif funcType == SOLLYA_BASE_FUNC_DOUBLEDOUBLE:
123
        return "doubleDouble"
124
    elif funcType == SOLLYA_BASE_FUNC_DOUBLEEXTENDED:
125
        return "doubleDxtended"
126
    elif funcType == SOLLYA_BASE_FUNC_ERF:
127
        return "erf"
128
    elif funcType == SOLLYA_BASE_FUNC_ERFC:
129
        return "erfc"
130
    elif funcType == SOLLYA_BASE_FUNC_EXP:
131
        return "exp"
132
    elif funcType == SOLLYA_BASE_FUNC_EXP_M1:
133
        return "expm1"
134
    elif funcType == SOLLYA_BASE_FUNC_FLOOR:
135
        return "floor"
136
    elif funcType == SOLLYA_BASE_FUNC_FREE_VARIABLE:
137
        return "freeVariable"
138
    elif funcType == SOLLYA_BASE_FUNC_HALFPRECISION:
139
        return "halfPrecision"
140
    elif funcType == SOLLYA_BASE_FUNC_LIBRARYCONSTANT:
141
        return "libraryConstant"
142
    elif funcType == SOLLYA_BASE_FUNC_LIBRARYFUNCTION:
143
        return "libraryFunction"
144
    elif funcType == SOLLYA_BASE_FUNC_LOG:
145
        return "log"
146
    elif funcType == SOLLYA_BASE_FUNC_LOG_10:
147
        return "log10"
148
    elif funcType == SOLLYA_BASE_FUNC_LOG_1P:
149
        return "log1p"
150
    elif funcType == SOLLYA_BASE_FUNC_LOG_2:
151
        return "log2"
152
    elif funcType == SOLLYA_BASE_FUNC_MUL:
153
        return "*"
154
    elif funcType == SOLLYA_BASE_FUNC_NEARESTINT:
155
        return "round"
156
    elif funcType == SOLLYA_BASE_FUNC_NEG:
157
        return "__neg__"
158
    elif funcType == SOLLYA_BASE_FUNC_PI:
159
        return "pi"
160
    elif funcType == SOLLYA_BASE_FUNC_POW:
161
        return "^"
162
    elif funcType == SOLLYA_BASE_FUNC_PROCEDUREFUNCTION:
163
        return "procedureFunction"
164
    elif funcType == SOLLYA_BASE_FUNC_QUAD:
165
        return "quad"
166
    elif funcType == SOLLYA_BASE_FUNC_SIN:
167
        return "sin"
168
    elif funcType == SOLLYA_BASE_FUNC_SINGLE:
169
        return "single"
170
    elif funcType == SOLLYA_BASE_FUNC_SINH:
171
        return "sinh"
172
    elif funcType == SOLLYA_BASE_FUNC_SQRT:
173
        return "sqrt"
174
    elif funcType == SOLLYA_BASE_FUNC_SUB:
175
        return "-"
176
    elif funcType == SOLLYA_BASE_FUNC_TAN:
177
        return "tan"
178
    elif funcType == SOLLYA_BASE_FUNC_TANH:
179
        return "tanh"
180
    elif funcType == SOLLYA_BASE_FUNC_TRIPLEDOUBLE:
181
        return "tripleDouble"
182
    else:
183
        return None
184

    
185
def pobyso_get_constant(rnArg, soConst):
186
    set_rn_value(rnArg, soConst)
187
    
188
def pobyso_get_constant_as_rn(ctExp):
189
    precision  = pobyso_get_prec_of_constant(ctExp) 
190
    RRRR = RealField(precision)
191
    rn = RRRR(0)
192
    sollya_lib_get_constant(get_rn_value(rn), ctExp)
193
    return(rn)
194
    
195
def pobyso_get_constant_as_rn_with_rf(ctExp, realField):
196
    rn = realField(0)
197
    sollya_lib_get_constant(get_rn_value(rn), ctExp)
198
    return(rn)
199
def pobyso_get_free_variable_name():
200
    return(sollya_lib_get_free_variable_name())
201
    
202
def pobyso_get_function_arity(expression):
203
    arity = c_int(0)
204
    sollya_lib_get_function_arity(byref(arity),expression)
205
    return(int(arity.value))
206

    
207
def pobyso_get_head_function(expression):
208
    functionType = c_int(0)
209
    sollya_lib_get_head_function(byref(functionType), expression, None)
210
    return(int(functionType.value))
211

    
212
def pobyso_get_list_elements(soObj):
213
    # Type for array of pointers to sollya_obj_t
214
    listAddress = POINTER(c_longlong)()
215
    numElements = c_int(0)
216
    isEndElliptic = c_int(0)
217
    listAsList = []
218
    result = sollya_lib_get_list_elements(byref(listAddress),\
219
                                        byref(numElements),\
220
                                        byref(isEndElliptic),\
221
                                        soObj)
222
    if result == 0 :
223
        return None
224
    for i in xrange(0, numElements.value, 1):
225
        print "address ", i, " ->", listAddress[i]
226
        listAsList.append(listAddress[i])
227
    return(listAsList, numElements.value, isEndElliptic.value)
228

    
229

    
230
# Get the maximum precision used for the numbers in a 
231
# Sollya expression.
232
# ToDo: 
233
# - error management;
234
# - correctly deal with numerical type such as DOUBLEEXTENDED.
235
def pobyso_get_max_prec_of_exp(soExp):
236
    maxPrecision = 0
237
    operator = pobyso_get_head_function(soExp)
238
    if (operator != SOLLYA_BASE_FUNC_CONSTANT) and \
239
    (operator != SOLLYA_BASE_FUNC_FREE_VARIABLE):
240
        (arity, subexpressions) = pobyso_get_subfunctions(soExp)
241
        for i in xrange(arity):
242
            maxPrecisionCandidate = \
243
            pobyso_get_max_prec_of_exp(subexpressions[i])
244
            if maxPrecisionCandidate > maxPrecision:
245
                maxPrecision = maxPrecisionCandidate
246
        return(maxPrecision)
247
    elif operator == SOLLYA_BASE_FUNC_CONSTANT:
248
        #print pobyso_get_prec_of_constant(soExp)
249
        return(pobyso_get_prec_of_constant(soExp))
250
    elif operator == SOLLYA_BASE_FUNC_FREE_VARIABLE:
251
        return(0)
252
    else:
253
        print "pobyso_get_max_prec_of_exp: unexepected operator."
254
        return(0)
255

    
256
def pobyso_get_sage_exp_from_sollya_exp(sollyaExp, realField = RR):
257
    """
258
    Get a Sage expression from a Sollya expression, currently only tested
259
    with polynomials with floating-point coefficients.
260
    Notice that, in the returned polynomial, the exponents are RealNumbers.
261
    """
262
    #pobyso_autoprint(sollyaExp)
263
    operator = pobyso_get_head_function(sollyaExp)
264
    # Constants and the free variable are special cases.
265
    # All other operator are dealt with in the same way.
266
    if (operator != SOLLYA_BASE_FUNC_CONSTANT) and \
267
       (operator != SOLLYA_BASE_FUNC_FREE_VARIABLE):
268
        (arity, subexpressions) = pobyso_get_subfunctions(sollyaExp)
269
        if arity == 1:
270
            sageExp = eval(pobyso_function_type_as_string(operator) + \
271
            "(" + pobyso_get_sage_exp_from_sollya_exp(subexpressions[0], realField)\
272
             + ")")
273
        elif arity == 2:
274
            if operator == SOLLYA_BASE_FUNC_POW:
275
                operatorAsString = "**"
276
            else:
277
                operatorAsString = pobyso_function_type_as_string(operator)
278
            sageExp = \
279
              eval("pobyso_get_sage_exp_from_sollya_exp(subexpressions[0], realField)"\
280
              + " " + operatorAsString + " " + \
281
                   "pobyso_get_sage_exp_from_sollya_exp(subexpressions[1], realField)")
282
        # We do not know yet how to deal with arity > 3 (is there any in Sollya anyway?).
283
        else:
284
            sageExp = eval('None')
285
        return(sageExp)
286
    elif operator == SOLLYA_BASE_FUNC_CONSTANT:
287
        #print "This is a constant"
288
        return pobyso_get_constant_as_rn_with_rf(sollyaExp, realField)
289
    elif operator == SOLLYA_BASE_FUNC_FREE_VARIABLE:
290
        #print "This is free variable"
291
        return(eval(sollya_lib_get_free_variable_name()))
292
    else:
293
        print "Unexpected"
294
        return eval('None')
295
# End pobyso_get_sage_poly_from_sollya_poly
296
    
297
def pobyso_get_subfunctions(expression):
298
    subf0 = c_int(0)
299
    subf1 = c_int(0)
300
    subf2 = c_int(0)
301
    subf3 = c_int(0)
302
    subf4 = c_int(0)
303
    subf5 = c_int(0)
304
    subf6 = c_int(0)
305
    subf7 = c_int(0)
306
    subf8 = c_int(0)
307
    arity = c_int(0)
308
    nullPtr = POINTER(c_int)()
309
    sollya_lib_get_subfunctions(expression, byref(arity), \
310
    byref(subf0), byref(subf1), byref(subf2), byref(subf3), byref(subf4), byref(subf5),\
311
     byref(subf6), byref(subf7), byref(subf8), nullPtr, None) 
312
#    byref(cast(subfunctions[0], POINTER(c_int))), byref(cast(subfunctions[0], POINTER(c_int))), \
313
#    byref(cast(subfunctions[2], POINTER(c_int))), byref(cast(subfunctions[3], POINTER(c_int))), \
314
#    byref(cast(subfunctions[4], POINTER(c_int))), byref(cast(subfunctions[5], POINTER(c_int))), \
315
#    byref(cast(subfunctions[6], POINTER(c_int))), byref(cast(subfunctions[7], POINTER(c_int))), \
316
#    byref(cast(subfunctions[8], POINTER(c_int))), nullPtr)
317
    subfunctions = [subf0, subf1, subf2, subf3, subf4, subf5, subf6, subf7, subf8]
318
    subs = []
319
    if arity.value > pobyso_max_arity:
320
        return(None,None)
321
    for i in xrange(arity.value):
322
        subs.append(int(subfunctions[i].value))
323
        #print subs[i]
324
    return(int(arity.value), subs)
325
    
326
def pobyso_get_prec():
327
    retc = sollya_lib_get_prec(None)
328
    a = c_int(0)
329
    sollya_lib_get_constant_as_int(byref(a), retc)
330
    return(int(a.value))
331

    
332
def pobyso_get_prec_of_constant(ctExp):
333
    prec = c_int(0)
334
    retc = sollya_lib_get_prec_of_constant(byref(prec), ctExp, None)
335
    return(int(prec.value))
336

    
337
def pobyso_lib_init():
338
    sollya_lib_init(None)
339
    
340
def pobyso_name_free_variable(freeVariableName):
341
    sollya_lib_name_free_variable(freeVariableName)
342

    
343
def pobyso_parse_string(string):
344
    return(sollya_lib_parse_string(string))
345

    
346
def pobyso_range(rnLowerBound, rnUpperBound):
347
    lowerBoundSo = sollya_lib_constant(get_rn_value(rnLowerBound))
348
    upperBoundSo = sollya_lib_constant(get_rn_value(rnUpperBound))
349
    rangeSo = sollya_lib_range(lowerBoundSo, upperBoundSo)
350
    return(rangeSo)
351

    
352
def pobyso_remez_canonical(function, \
353
                           degree, \
354
                           lowerBound, \
355
                           upperBound, \
356
                           weightSo = pobyso_constant_1(),
357
                           quality = None):
358
    if parent(function) == parent("string"):
359
        functionSo = sollya_lib_parse_string(function)
360
    #    print "Is string!"
361
    elif sollya_lib_obj_is_function(function):
362
        functionSo = function
363
    #    print "Is Function!"
364
    degreeSo = pobyso_constant_from_int(degree)
365
    rangeSo = pobyso_range(lowerBound, upperBound)
366
    return(sollya_lib_remez(functionSo, degreeSo, rangeSo, quality, None))
367
    
368
def pobyso_set_canonical_off():
369
    sollya_lib_set_canonical(sollya_lib_off())
370

    
371
def pobyso_set_canonical_on():
372
    sollya_lib_set_canonical(sollya_lib_on())
373

    
374
def pobyso_set_prec(p):
375
    a = c_int(p)
376
    precSo = c_void_p(sollya_lib_constant_from_int(a))
377
    sollya_lib_set_prec(precSo)
378

    
379
def pobyso_taylor(function, degree, point):
380
    return(sollya_lib_taylor(function, degree, point))
381
    
382
# TODO: take care of the interval and of point when it is an interval;
383
#       when errorType is not None;
384
#       take care of the other elements of the Taylor form (coefficients errors and
385
#       delta.
386
def pobyso_taylorform(function, degree, point = None, interval = None, errorType=None):
387
    """
388
    Compute the Taylor form of 'degre' for 'function' at 'point' 
389
    for 'interval' with 'errorType'. 
390
    point: must be a Real or a Real interval.
391
    return the Taylor form as an array
392
    """
393
    # Absolute as the default error.
394
    if errorType is None:
395
        errorTypeSo = sollya_lib_absolute()
396
    else:
397
        #TODO: deal with the other case.
398
        pass
399
    varSa = function.variables()[0]
400
    pointBaseRingString = str(point.base_ring())
401
    if not re.search('Real', pointBaseRingString):
402
        return None
403
    # Call Sollya but first "sollyafy" the arguments.
404
    sollya_lib_init(None)
405
    pobyso_name_free_variable(str(varSa))
406
    # Sollyafy the function.
407
    functionSo = pobyso_parse_string(function._assume_str())
408
    if sollya_lib_obj_is_error(functionSo):
409
        print "pobyso_tailorform: function string can't be parsed!"
410
        return None
411
    # Sollyafy the degree
412
    degreeSo = sollya_lib_constant_from_int(int(degree))
413
    # Sollyafy the point
414
    if not re.search('Interval', pointBaseRingString):
415
        pointSo  = pobyso_constant(point)
416
    else:
417
        # TODO: deal with the interval case.
418
        pass
419
    # Call Sollya
420
    taylorFormSo = sollya_lib_taylorform(functionSo, degreeSo, pointSo, errorTypeSo,\
421
                                         None)
422
    (tfsAsList, numElements, isEndElliptic) = pobyso_get_list_elements(taylorFormSo)
423
    polySo = tfsAsList[0]
424
    maxPrecision = pobyso_get_max_prec_of_exp(polySo)
425
    polyRealField = RealField(maxPrecision)
426
    expSa = pobyso_get_sage_exp_from_sollya_exp(polySo, polyRealField)
427
    sollya_lib_close()
428
    polynomialRing = polyRealField[str(varSa)]
429
    polySa = polynomial(expSa, polynomialRing)
430
    taylorFormSa = [polySa]
431
    return(taylorFormSa)                    
432

    
433
def pobyso_univar_polynomial_print_reverse(polySa):
434
    """
435
    Return the string representation of a univariate polynomial with
436
    monomial ordered in the x^0..x^n order of the monomials.
437
    Remember: Sage
438
    """
439
    polynomialRing = polySa.base_ring()
440
    # A very expensive solution:
441
    # -create a fake multivariate polynomial field with only one variable,
442
    #   specifying a negative lexicographical order;
443
    mpolynomialRing = PolynomialRing(polynomialRing.base(), \
444
                                     polynomialRing.variable_name(), \
445
                                     1, order='neglex')
446
    # - convert the univariate argument polynomial into a multivariate
447
    #   version;
448
    p = mpolynomialRing(polySa)
449
    # - return the string representation of the converted form.
450
    # There is no simple str() method defined for p's class.
451
    return(p.__str__())
452
#
453
print "Superficial test of pobyso:"    
454
print pobyso_get_prec()  
455
pobyso_set_prec(165)
456
print pobyso_get_prec()  
457
a=100
458
print type(a)
459
id(a)
460
print "Max arity: ", pobyso_max_arity
461
print "Function tripleDouble (43) as a string: ", pobyso_function_type_as_string(43)
462
print "Function None (44) as a string: ", pobyso_function_type_as_string(44)