Statistiques
| Révision :

root / pobysoPythonSage / src / pobyso.py @ 83

Historique | Voir | Annoter | Télécharger (39,01 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
pobyso functions come in five flavors: 
9
- the _so_so (arguments and returned objects are pointers to Sollya objects, 
10
  includes the void function and the no arguments function that return a 
11
  pointer to a Sollya object);
12
- the _so_sa (argument are pointers to Sollya objects, returned objects are
13
  Sage/Python objects or, more generally, information is transfered from the
14
  Sollya world to Sage/Python world; e.g. functions without arguments that
15
  return a Sage/Python object);
16
- the _sa_so (arguments are Sage/Python objects, returned objects are 
17
  pointers to Sollya objects);
18
- the sa_sa (arguments and returned objects are all Sage/Python objects);
19
- a catch all flavor, without any suffix, (e. g. functions that have no argument 
20
  nor return value).
21
This classification is not always very strict. Conversion functions from Sollya
22
to Sage/Python are sometimes decorated with Sage/Python arguments to set
23
the precision. These functions remain in the so_sa category.
24
NOTES:
25
Reported errors in Eclipse come from the calls to
26
the Sollya library
27

28
ToDo (among other things): 
29
 -memory management.
30
"""
31
from ctypes import *
32
import re
33
from sage.symbolic.expression_conversions import polynomial
34
from sage.symbolic.expression_conversions import PolynomialConverter
35
"""
36
Create the equivalent to an enum for the Sollya function types.
37
"""
38
(SOLLYA_BASE_FUNC_ABS,
39
SOLLYA_BASE_FUNC_ACOS,
40
    SOLLYA_BASE_FUNC_ACOSH,
41
    SOLLYA_BASE_FUNC_ADD,
42
    SOLLYA_BASE_FUNC_ASIN,
43
    SOLLYA_BASE_FUNC_ASINH,
44
    SOLLYA_BASE_FUNC_ATAN,
45
    SOLLYA_BASE_FUNC_ATANH,
46
    SOLLYA_BASE_FUNC_CEIL,
47
    SOLLYA_BASE_FUNC_CONSTANT,
48
    SOLLYA_BASE_FUNC_COS,
49
    SOLLYA_BASE_FUNC_COSH,
50
    SOLLYA_BASE_FUNC_DIV,
51
    SOLLYA_BASE_FUNC_DOUBLE,
52
    SOLLYA_BASE_FUNC_DOUBLEDOUBLE,
53
    SOLLYA_BASE_FUNC_DOUBLEEXTENDED,
54
    SOLLYA_BASE_FUNC_ERF,
55
    SOLLYA_BASE_FUNC_ERFC,
56
    SOLLYA_BASE_FUNC_EXP,
57
    SOLLYA_BASE_FUNC_EXP_M1,
58
    SOLLYA_BASE_FUNC_FLOOR,
59
    SOLLYA_BASE_FUNC_FREE_VARIABLE,
60
    SOLLYA_BASE_FUNC_HALFPRECISION,
61
    SOLLYA_BASE_FUNC_LIBRARYCONSTANT,
62
    SOLLYA_BASE_FUNC_LIBRARYFUNCTION,
63
    SOLLYA_BASE_FUNC_LOG,
64
    SOLLYA_BASE_FUNC_LOG_10,
65
    SOLLYA_BASE_FUNC_LOG_1P,
66
    SOLLYA_BASE_FUNC_LOG_2,
67
    SOLLYA_BASE_FUNC_MUL,
68
    SOLLYA_BASE_FUNC_NEARESTINT,
69
    SOLLYA_BASE_FUNC_NEG,
70
    SOLLYA_BASE_FUNC_PI,
71
    SOLLYA_BASE_FUNC_POW,
72
    SOLLYA_BASE_FUNC_PROCEDUREFUNCTION,
73
    SOLLYA_BASE_FUNC_QUAD,
74
    SOLLYA_BASE_FUNC_SIN,
75
    SOLLYA_BASE_FUNC_SINGLE,
76
    SOLLYA_BASE_FUNC_SINH,
77
    SOLLYA_BASE_FUNC_SQRT,
78
    SOLLYA_BASE_FUNC_SUB,
79
    SOLLYA_BASE_FUNC_TAN,
80
    SOLLYA_BASE_FUNC_TANH,
81
SOLLYA_BASE_FUNC_TRIPLEDOUBLE) = map(int,xrange(44))
82
print "\nSuperficial pobyso check..."    
83
print "First constant - SOLLYA_BASE_FUNC_ABS: ", SOLLYA_BASE_FUNC_ABS
84
print "Last constant  - SOLLYA_BASE_FUNC_TRIPLEDOUBLE: ", SOLLYA_BASE_FUNC_TRIPLEDOUBLE
85

    
86
pobyso_max_arity = 9
87

    
88
def pobyso_autoprint(arg):
89
    sollya_lib_autoprint(arg,None)
90

    
91
def pobyso_autoprint_so_so(arg):
92
    sollya_lib_autoprint(arg,None)
93
    
94
def pobyso_absolute_so_so():
95
    return(sollya_lib_absolute(None))
96

    
97
def pobyso_build_function_sub_so_so(exp1So, exp2So):
98
    return(sollya_lib_build_function_sub(exp1So, exp2So))
99

    
100
def pobyso_cmp(rnArg, soCte):
101
    """
102
    Compare the MPFR value a RealNumber with that of a Sollya constant.
103
    
104
    Get the value of the Sollya constant into a RealNumber and compare
105
    using MPFR. Could be optimized by working directly with a mpfr_t
106
    for the intermediate number. 
107
    """
108
    precisionOfCte = c_int(0)
109
    # From the Sollya constant, create a local Sage RealNumber.
110
    sollya_lib_get_prec_of_constant(precisionOfCte, soCte) 
111
    #print "Precision of constant: ", precisionOfCte
112
    RRRR = RealField(precisionOfCte.value)
113
    rnLocal = RRRR(0)
114
    sollya_lib_get_constant(get_rn_value(rnLocal), soCte)
115
    #print "rnDummy: ", rnDummy
116
    # Compare the local Sage RealNumber with rnArg.
117
    return(cmp_rn_value(rnArg, rnLocal))
118
# End pobyso_smp
119

    
120
def pobyso_change_var_in_function_so_so(funcSo, chvarExpSo):
121
    """
122
    Variable change in a function.
123
    """
124
    return(sollya_lib_evaluate(funcSo,chvarExpSo))
125
# End pobyso_change_var_in_function_so_so     
126

    
127
def pobyso_chebyshevform_so_so(functionSo, degreeSo, intervalSo):
128
    resultSo = sollya_lib_chebyshevform(functionSo, degreeSo, intervalSo)
129
    return(resultSo)
130
# End pobyso_chebyshevform_so_so.
131

    
132
def pobyso_compute_pos_function_abs_val_bounds_sa_sa(funcSa, lowerBoundSa, \
133
                                                     upperBoundSa):
134
    """
135
    TODO: set the variable name in Sollya.
136
    """
137
    funcSo = pobyso_parse_string(funcSa._assume_str())
138
    rangeSo = pobyso_range_sa_so(lowerBoundSa, upperBoundSa)
139
    infnormSo = pobyso_infnorm_so_so(funcSo,rangeSo)
140
    # Sollya return the infnorm as an interval.
141
    fMaxSa = pobyso_get_interval_from_range_so_sa(infnormSo)
142
    # Get the top bound and compute the binade top limit.
143
    fMaxUpperBoundSa = fMaxSa.upper()
144
    binadeTopLimitSa = 2**ceil(fMaxUpperBoundSa.log2())
145
    # Put up together the function to use to compute the lower bound.
146
    funcAuxSo = pobyso_parse_string(str(binadeTopLimitSa) +  \
147
                                    '-(' + f._assume_str() + ')')
148
    pobyso_autoprint(funcAuxSo)
149
    # Clear the Sollya range before a new call to infnorm and issue the call.
150
    sollya_lib_clear_obj(infnormSo)
151
    infnormSo = pobyso_infnorm_so_so(funcAuxSo,rangeSo)
152
    fMinSa = pobyso_get_interval_from_range_so_sa(infnormSo)
153
    sollya_lib_clear_obj(infnormSo)
154
    fMinLowerBoundSa = topBinadeLimit - fMinSa.lower()
155
    # Compute the maximum of the precisions of the different bounds.
156
    maxPrecSa = max([fMinLowerBoundSa.parent().precision(), \
157
                     fMaxUpperBoundSa.parent().precision()])
158
    # Create a RealIntervalField and create an interval with the "good" bounds.
159
    RRRI = RealIntervalField(maxPrecSa)
160
    imageIntervalSa = RRRI(fMinLowerBoundSa, fMaxUpperBoundSa)
161
    # Free the unneeded Sollya objects
162
    sollya_lib_clear_obj(funcSo)
163
    sollya_lib_clear_obj(funcAuxSo)
164
    sollya_lib_clear_obj(rangeSo)
165
    return(imageIntervalSa)
166
# End pobyso_compute_pos_function_abs_val_bounds_sa_sa
167

    
168
def pobyso_constant(rnArg):
169
    """ Legacy function. See pobyso_constant_sa_so. """
170
    return(pobyso_constant_sa_so(rnArg))
171
    
172
def pobyso_constant_sa_so(rnArg):
173
    """
174
    Create a Sollya constant from a RealNumber.
175
    """
176
    return(sollya_lib_constant(get_rn_value(rnArg)))
177
    
178
def pobyso_constant_0_sa_so():
179
    return(pobyso_constant_from_int_sa_so(0))
180

    
181
def pobyso_constant_1():
182
    """ Legacy function. See pobyso_constant_so_so. """
183
    return(pobyso_constant_1_sa_so())
184

    
185
def pobyso_constant_1_sa_so():
186
    return(pobyso_constant_from_int_sa_so(1))
187

    
188
def pobyso_constant_from_int(anInt):
189
    """ Legacy function. See pobyso_constant_from_int_sa_so. """
190
    return(pobyso_constant_from_int_sa_so(anInt))
191

    
192
def pobyso_constant_from_int_sa_so(anInt):
193
    return(sollya_lib_constant_from_int(int(anInt)))
194

    
195
def pobyso_function_type_as_string(funcType):
196
    """ Legacy function. See pobyso_function_type_as_string_so_sa. """
197
    return(pobyso_function_type_as_string_so_sa(funcType))
198

    
199
def pobyso_function_type_as_string_so_sa(funcType):
200
    """
201
    Numeric Sollya function codes -> Sage mathematical function names.
202
    Notice that pow -> ^ (a la Sage, not a la Python).
203
    """
204
    if funcType == SOLLYA_BASE_FUNC_ABS:
205
        return "abs"
206
    elif funcType == SOLLYA_BASE_FUNC_ACOS:
207
        return "arccos"
208
    elif funcType == SOLLYA_BASE_FUNC_ACOSH:
209
        return "arccosh"
210
    elif funcType == SOLLYA_BASE_FUNC_ADD:
211
        return "+"
212
    elif funcType == SOLLYA_BASE_FUNC_ASIN:
213
        return "arcsin"
214
    elif funcType == SOLLYA_BASE_FUNC_ASINH:
215
        return "arcsinh"
216
    elif funcType == SOLLYA_BASE_FUNC_ATAN:
217
        return "arctan"
218
    elif funcType == SOLLYA_BASE_FUNC_ATANH:
219
        return "arctanh"
220
    elif funcType == SOLLYA_BASE_FUNC_CEIL:
221
        return "ceil"
222
    elif funcType == SOLLYA_BASE_FUNC_CONSTANT:
223
        return "cte"
224
    elif funcType == SOLLYA_BASE_FUNC_COS:
225
        return "cos"
226
    elif funcType == SOLLYA_BASE_FUNC_COSH:
227
        return "cosh"
228
    elif funcType == SOLLYA_BASE_FUNC_DIV:
229
        return "/"
230
    elif funcType == SOLLYA_BASE_FUNC_DOUBLE:
231
        return "double"
232
    elif funcType == SOLLYA_BASE_FUNC_DOUBLEDOUBLE:
233
        return "doubleDouble"
234
    elif funcType == SOLLYA_BASE_FUNC_DOUBLEEXTENDED:
235
        return "doubleDxtended"
236
    elif funcType == SOLLYA_BASE_FUNC_ERF:
237
        return "erf"
238
    elif funcType == SOLLYA_BASE_FUNC_ERFC:
239
        return "erfc"
240
    elif funcType == SOLLYA_BASE_FUNC_EXP:
241
        return "exp"
242
    elif funcType == SOLLYA_BASE_FUNC_EXP_M1:
243
        return "expm1"
244
    elif funcType == SOLLYA_BASE_FUNC_FLOOR:
245
        return "floor"
246
    elif funcType == SOLLYA_BASE_FUNC_FREE_VARIABLE:
247
        return "freeVariable"
248
    elif funcType == SOLLYA_BASE_FUNC_HALFPRECISION:
249
        return "halfPrecision"
250
    elif funcType == SOLLYA_BASE_FUNC_LIBRARYCONSTANT:
251
        return "libraryConstant"
252
    elif funcType == SOLLYA_BASE_FUNC_LIBRARYFUNCTION:
253
        return "libraryFunction"
254
    elif funcType == SOLLYA_BASE_FUNC_LOG:
255
        return "log"
256
    elif funcType == SOLLYA_BASE_FUNC_LOG_10:
257
        return "log10"
258
    elif funcType == SOLLYA_BASE_FUNC_LOG_1P:
259
        return "log1p"
260
    elif funcType == SOLLYA_BASE_FUNC_LOG_2:
261
        return "log2"
262
    elif funcType == SOLLYA_BASE_FUNC_MUL:
263
        return "*"
264
    elif funcType == SOLLYA_BASE_FUNC_NEARESTINT:
265
        return "round"
266
    elif funcType == SOLLYA_BASE_FUNC_NEG:
267
        return "__neg__"
268
    elif funcType == SOLLYA_BASE_FUNC_PI:
269
        return "pi"
270
    elif funcType == SOLLYA_BASE_FUNC_POW:
271
        return "^"
272
    elif funcType == SOLLYA_BASE_FUNC_PROCEDUREFUNCTION:
273
        return "procedureFunction"
274
    elif funcType == SOLLYA_BASE_FUNC_QUAD:
275
        return "quad"
276
    elif funcType == SOLLYA_BASE_FUNC_SIN:
277
        return "sin"
278
    elif funcType == SOLLYA_BASE_FUNC_SINGLE:
279
        return "single"
280
    elif funcType == SOLLYA_BASE_FUNC_SINH:
281
        return "sinh"
282
    elif funcType == SOLLYA_BASE_FUNC_SQRT:
283
        return "sqrt"
284
    elif funcType == SOLLYA_BASE_FUNC_SUB:
285
        return "-"
286
    elif funcType == SOLLYA_BASE_FUNC_TAN:
287
        return "tan"
288
    elif funcType == SOLLYA_BASE_FUNC_TANH:
289
        return "tanh"
290
    elif funcType == SOLLYA_BASE_FUNC_TRIPLEDOUBLE:
291
        return "tripleDouble"
292
    else:
293
        return None
294

    
295
def pobyso_get_constant(rnArg, soConst):
296
    """ Legacy function. See pobyso_get_constant_so_sa. """
297
    return(pobyso_get_constant_so_sa(rnArg, soConst))
298

    
299
def pobyso_get_constant_so_sa(rnArg, soConst):
300
    """
301
    Set the value of rnArg to the value of soConst in MPFR_RNDN mode.
302
    rnArg must already exist and belong to some RealField.
303
    We assume that soConst points to a Sollya constant.
304
    """
305
    return(sollya_lib_get_constant(get_rn_value(rnArg), soConst))
306
    
307
def pobyso_get_constant_as_rn(ctExpSo):
308
    """ 
309
    Legacy function. See pobyso_get_constant_as_rn_so_sa. 
310
    """ 
311
    return(pobyso_get_constant_as_rn_so_sa(ctExpSo))
312
    
313
def pobyso_get_constant_as_rn_so_sa(constExpSo):
314
    """
315
    Get a Sollya constant as a Sage "real number".
316
    The precision of the floating-point number returned is that of the Sollya
317
    constant.
318
    """
319
    precisionSa  = pobyso_get_prec_of_constant_so_sa(constExpSo) 
320
    RRRR = RealField(precisionSa)
321
    rnSa = RRRR(0)
322
    sollya_lib_get_constant(get_rn_value(rnSa), constExpSo)
323
    return(rnSa)
324
# End pobyso_get_constant_as_rn_so_sa
325

    
326
def pobyso_get_constant_as_rn_with_rf(ctExp, realField):
327
    """ 
328
    Legacy function. See pobyso_get_constant_as_rn_with_rf_so_sa.
329
    """
330
    return(pobyso_get_constant_as_rn_with_rf_so_sa(ctExp, realField))
331
    
332
def pobyso_get_constant_as_rn_with_rf_so_sa(ctExpSo, realFieldSa = None):
333
    """
334
    Get a Sollya constant as a Sage "real number".
335
    If no real field is specified, the precision of the floating-point number 
336
    returned is that of the Solly constant.
337
    Otherwise is is that of the real field. Hence rounding may happen.
338
    """
339
    if realFieldSa is None:
340
        sollyaPrecSa = pobyso_get_prec_so_sa()
341
        realFieldSa = RealField(sollyaPrecSa)
342
    rnSa = realFieldSa(0)
343
    sollya_lib_get_constant(get_rn_value(rnSa), ctExpSo)
344
    return(rnSa)
345
# End pobyso_get_constant_as_rn_with_rf_so_sa
346

    
347
def pobyso_get_free_variable_name():
348
    """ 
349
    Legacy function. See pobyso_get_free_variable_name_so_sa.
350
    """
351
    return(pobyso_get_free_variable_name_so_sa())
352

    
353
def pobyso_get_free_variable_name_so_sa():
354
    return(sollya_lib_get_free_variable_name())
355
    
356
def pobyso_get_function_arity(expressionSo):
357
    """ 
358
    Legacy function. See pobyso_get_function_arity_so_sa.
359
    """
360
    return(pobyso_get_function_arity_so_sa(expressionSo))
361

    
362
def pobyso_get_function_arity_so_sa(expressionSo):
363
    arity = c_int(0)
364
    sollya_lib_get_function_arity(byref(arity),expressionSo)
365
    return(int(arity.value))
366

    
367
def pobyso_get_head_function(expressionSo):
368
    """ 
369
    Legacy function. See pobyso_get_head_function_so_sa. 
370
    """
371
    return(pobyso_get_head_function_so_sa(expressionSo)) 
372

    
373
def pobyso_get_head_function_so_sa(expressionSo):
374
    functionType = c_int(0)
375
    sollya_lib_get_head_function(byref(functionType), expressionSo, None)
376
    return(int(functionType.value))
377

    
378
def pobyso_get_interval_from_range_so_sa(soRange, realIntervalFieldSa = None ):
379
    """
380
    Return the Sage interval corresponding to the Sollya range argument.
381
    If no reaIntervalField is passed as an argument, the interval bounds are not
382
    rounded: they are elements of RealIntervalField of the "right" precision
383
    to hold all the digits.
384
    """
385
    prec = c_int(0)
386
    if realIntervalFieldSa is None:
387
        retval = sollya_lib_get_prec_of_range(byref(prec), soRange, None)
388
        if retval == 0:
389
            return(None)
390
        realIntervalFieldSa = RealIntervalField(prec.value)
391
    intervalSa = realIntervalFieldSa(0,0)
392
    retval = \
393
        sollya_lib_get_interval_from_range(get_interval_value(intervalSa),\
394
                                           soRange)
395
    if retval == 0:
396
        return(None)
397
    return(intervalSa)
398
# End pobyso_get_interval_from_range_so_sa
399

    
400
def pobyso_get_list_elements(soObj):
401
    """ Legacy function. See pobyso_get_list_elements_so_so. """
402
    return(pobyso_get_list_elements_so_so(soObj))
403
 
404
def pobyso_get_list_elements_so_so(soObj):
405
    """
406
    Get the list elements as a Sage/Python array of Sollya objects.
407
    The other data returned are also Sage/Python objects.
408
    """
409
    listAddress = POINTER(c_longlong)()
410
    numElements = c_int(0)
411
    isEndElliptic = c_int(0)
412
    listAsList = []
413
    result = sollya_lib_get_list_elements(byref(listAddress),\
414
                                          byref(numElements),\
415
                                          byref(isEndElliptic),\
416
                                          soObj)
417
    if result == 0 :
418
        return None
419
    for i in xrange(0, numElements.value, 1):
420
        listAsList.append(listAddress[i])
421
    return(listAsList, numElements.value, isEndElliptic.value)
422

    
423
def pobyso_get_max_prec_of_exp(soExp):
424
    """ Legacy function. See pobyso_get_max_prec_of_exp_so_sa. """
425
    return(pobyso_get_max_prec_of_exp_so_sa(soExp))
426

    
427
def pobyso_get_max_prec_of_exp_so_sa(soExp):
428
    """
429
    Get the maximum precision used for the numbers in a Sollya expression.
430
    
431
    Arguments:
432
    soExp -- a Sollya expression pointer
433
    Return value:
434
    A Python integer
435
    TODO: 
436
    - error management;
437
    - correctly deal with numerical type such as DOUBLEEXTENDED.
438
    """
439
    maxPrecision = 0
440
    minConstPrec = 0
441
    currentConstPrec = 0
442
    operator = pobyso_get_head_function_so_sa(soExp)
443
    if (operator != SOLLYA_BASE_FUNC_CONSTANT) and \
444
    (operator != SOLLYA_BASE_FUNC_FREE_VARIABLE):
445
        (arity, subexpressions) = pobyso_get_subfunctions_so_sa(soExp)
446
        for i in xrange(arity):
447
            maxPrecisionCandidate = \
448
                pobyso_get_max_prec_of_exp_so_sa(subexpressions[i])
449
            if maxPrecisionCandidate > maxPrecision:
450
                maxPrecision = maxPrecisionCandidate
451
        return(maxPrecision)
452
    elif operator == SOLLYA_BASE_FUNC_CONSTANT:
453
        minConstPrec = pobyso_get_min_prec_of_constant_so_sa(soExp)
454
        #currentConstPrec = pobyso_get_min_prec_of_constant_so_sa(soExp)
455
        #print minConstPrec, " - ", currentConstPrec 
456
        return(pobyso_get_min_prec_of_constant_so_sa(soExp))
457
    
458
    elif operator == SOLLYA_BASE_FUNC_FREE_VARIABLE:
459
        return(0)
460
    else:
461
        print "pobyso_get_max_prec_of_exp_so_sa: unexepected operator."
462
        return(0)
463

    
464
def pobyso_get_min_prec_of_constant_so_sa(soConstExp):
465
    """
466
    Get the minimum precision necessary to represent the value of a Sollya
467
    constant.
468
    MPFR_MIN_PREC and powers of 2 are taken into account.
469
    We assume that soCteExp is a point
470
    """
471
    constExpAsRn = pobyso_get_constant_as_rn_so_sa(soConstExp)
472
    return(min_mpfr_size(get_rn_value(constExpAsRn)))
473

    
474
def pobyso_get_sage_exp_from_sollya_exp(sollyaExp, realField = RR):
475
    """ Legacy function. See pobyso_get_sage_exp_from_sollya_exp_so_sa. """
476
    return(pobyso_get_sage_exp_from_sollya_exp_so_sa(sollyaExp, realField = RR))
477

    
478
def pobyso_get_sage_exp_from_sollya_exp_so_sa(sollyaExp, realField = RR):
479
    """
480
    Get a Sage expression from a Sollya expression. 
481
    Currently only tested with polynomials with floating-point coefficients.
482
    Notice that, in the returned polynomial, the exponents are RealNumbers.
483
    """
484
    #pobyso_autoprint(sollyaExp)
485
    operator = pobyso_get_head_function_so_sa(sollyaExp)
486
    sollyaLibFreeVariableName = sollya_lib_get_free_variable_name()
487
    # Constants and the free variable are special cases.
488
    # All other operator are dealt with in the same way.
489
    if (operator != SOLLYA_BASE_FUNC_CONSTANT) and \
490
       (operator != SOLLYA_BASE_FUNC_FREE_VARIABLE):
491
        (arity, subexpressions) = pobyso_get_subfunctions_so_sa(sollyaExp)
492
        if arity == 1:
493
            sageExp = eval(pobyso_function_type_as_string_so_sa(operator) + \
494
            "(" + pobyso_get_sage_exp_from_sollya_exp_so_sa(subexpressions[0], \
495
            realField) + ")")
496
        elif arity == 2:
497
            # We do not get through the preprocessor.
498
            # The "^" operator is then a special case.
499
            if operator == SOLLYA_BASE_FUNC_POW:
500
                operatorAsString = "**"
501
            else:
502
                operatorAsString = \
503
                    pobyso_function_type_as_string_so_sa(operator)
504
            sageExp = \
505
              eval("pobyso_get_sage_exp_from_sollya_exp_so_sa(subexpressions[0], realField)"\
506
              + " " + operatorAsString + " " + \
507
                   "pobyso_get_sage_exp_from_sollya_exp_so_sa(subexpressions[1], realField)")
508
        # We do not know yet how to deal with arity >= 3 
509
        # (is there any in Sollya anyway?).
510
        else:
511
            sageExp = eval('None')
512
        return(sageExp)
513
    elif operator == SOLLYA_BASE_FUNC_CONSTANT:
514
        #print "This is a constant"
515
        return pobyso_get_constant_as_rn_with_rf_so_sa(sollyaExp, realField)
516
    elif operator == SOLLYA_BASE_FUNC_FREE_VARIABLE:
517
        #print "This is free variable"
518
        return(eval(sollyaLibFreeVariableName))
519
    else:
520
        print "Unexpected"
521
        return eval('None')
522
# End pobyso_get_sage_poly_from_sollya_poly
523

    
524
def pobyso_get_poly_sa_so(polySo, realFieldSa=None):
525
    """
526
    Create a Sollya polynomial from a Sage polynomial.
527
    """
528
    pass
529
# pobyso_get_poly_sa_so
530

    
531
def pobyso_get_poly_so_sa(polySo, realFieldSa=None):
532
    """
533
    Convert a Sollya polynomial into a Sage polynomial.
534
    We assume that the polynomial is in canonical form.
535
    If no realField is given, a RealField corresponding to the maximum precision 
536
    of the coefficients is internally computed.
537
    It is not returned but can be easily retrieved from the polynomial itself.
538
    Main steps:
539
    - (optional) compute the RealField of the coefficients;
540
    - convert the Sollya expression into a Sage expression;
541
    - convert the Sage expression into a Sage polynomial
542
    TODO: the canonical thing for the polynomial.
543
    """    
544
    if realFieldSa is None:
545
        expressionPrecSa = pobyso_get_max_prec_of_exp_so_sa(polySo)
546
        realFieldSa = RealField(expressionPrecSa)
547
    #print "Sollya expression before...",
548
    #pobyso_autoprint(polySo)
549

    
550
    expressionSa = pobyso_get_sage_exp_from_sollya_exp_so_sa(polySo, \
551
                                                             realFieldSa)
552
    #print "...Sollya expression after.",
553
    #pobyso_autoprint(polySo)
554
    polyVariableSa = expressionSa.variables()[0]
555
    polyRingSa = realFieldSa[str(polyVariableSa)]
556
    #print polyRingSa
557
    # Do not use the polynomial(expressionSa, ring=polyRingSa) form!
558
    polynomialSa = polyRingSa(expressionSa)
559
    return(polynomialSa)
560
# End pobyso_get_sage_poly_from_sollya_poly
561

    
562
def pobyso_get_subfunctions(expressionSo):
563
    """ Legacy function. See pobyso_get_subfunctions_so_sa. """
564
    return(pobyso_get_subfunctions_so_sa(expressionSo)) 
565

    
566
def pobyso_get_subfunctions_so_sa(expressionSo):
567
    """
568
    Get the subfunctions of an expression.
569
    Return the number of subfunctions and the list of subfunctions addresses.
570
    S.T.: Could not figure out another way than that ugly list of declarations
571
    to recover the addresses of the subfunctions.
572
    We limit ourselves to arity 8 functions. 
573
    """
574
    subf0 = c_int(0)
575
    subf1 = c_int(0)
576
    subf2 = c_int(0)
577
    subf3 = c_int(0)
578
    subf4 = c_int(0)
579
    subf5 = c_int(0)
580
    subf6 = c_int(0)
581
    subf7 = c_int(0)
582
    subf8 = c_int(0)
583
    arity = c_int(0)
584
    nullPtr = POINTER(c_int)()
585
    sollya_lib_get_subfunctions(expressionSo, byref(arity), \
586
      byref(subf0), byref(subf1), byref(subf2), byref(subf3), \
587
      byref(subf4), byref(subf5),\
588
      byref(subf6), byref(subf7), byref(subf8), nullPtr, None) 
589
#    byref(cast(subfunctions[0], POINTER(c_int))), \
590
#    byref(cast(subfunctions[0], POINTER(c_int))), \
591
#    byref(cast(subfunctions[2], POINTER(c_int))), \
592
#    byref(cast(subfunctions[3], POINTER(c_int))), \
593
#    byref(cast(subfunctions[4], POINTER(c_int))), \
594
#    byref(cast(subfunctions[5], POINTER(c_int))), \
595
#    byref(cast(subfunctions[6], POINTER(c_int))), \
596
#    byref(cast(subfunctions[7], POINTER(c_int))), \
597
#    byref(cast(subfunctions[8], POINTER(c_int))), nullPtr)
598
    subfunctions = [subf0, subf1, subf2, subf3, subf4, subf5, subf6, subf7, \
599
                    subf8]
600
    subs = []
601
    if arity.value > pobyso_max_arity:
602
        return(0,[])
603
    for i in xrange(arity.value):
604
        subs.append(int(subfunctions[i].value))
605
        #print subs[i]
606
    return(int(arity.value), subs)
607
    
608
def pobyso_get_prec():
609
    """ Legacy function. See pobyso_get_prec_so_sa(). """
610
    return(pobyso_get_prec_so_sa())
611

    
612
def pobyso_get_prec_so_sa():
613
    """
614
    Get the current default precision in Sollya.
615
    The return value is Sage/Python int.
616
    """
617
    precSo = sollya_lib_get_prec(None)
618
    precSa = c_int(0)
619
    sollya_lib_get_constant_as_int(byref(precSa), precSo)
620
    sollya_lib_clear_obj(precSo)
621
    return(int(precSa.value))
622
# End pobyso_get_prec_so_sa.
623

    
624
def pobyso_get_prec_of_constant(ctExpSo):
625
    """ Legacy function. See pobyso_get_prec_of_constant_so_sa. """
626
    return(pobyso_get_prec_of_constant_so_sa(ctExpSo))
627

    
628
def pobyso_get_prec_of_constant_so_sa(ctExpSo):
629
    prec = c_int(0)
630
    retc = sollya_lib_get_prec_of_constant(byref(prec), ctExpSo, None)
631
    if retc == 0:
632
        return(None)
633
    return(int(prec.value))
634

    
635
def pobyso_get_prec_of_range_so_sa(rangeSo):
636
    prec = c_int(0)
637
    retc = sollya_lib_get_prec_of_range(byref(prec), rangeSo, None)
638
    if retc == 0:
639
        return(None)
640
    return(int(prec.value))
641

    
642
def pobyso_infnorm_so_so(func, interval, file = None, intervalList = None):
643
    print "Do not use this function. User pobyso_supnorm_so_so instead."
644
    return(None)
645

    
646
def pobyso_lib_init():
647
    sollya_lib_init(None)
648
    
649
def pobyso_name_free_variable(freeVariableName):
650
    """ Legacy function. See pobyso_name_free_variable_sa_so. """
651
    pobyso_name_free_variable_sa_so(freeVariableName)
652

    
653
def pobyso_name_free_variable_sa_so(freeVariableName):
654
    """
655
    Set the free variable name in Sollya from a Sage string.
656
    """
657
    sollya_lib_name_free_variable(freeVariableName)
658

    
659
def pobyso_parse_string(string):
660
    """ Legacy function. See pobyso_parse_string_sa_so. """
661
    return(pobyso_parse_string_sa_so(string))
662
 
663
def pobyso_parse_string_sa_so(string):
664
    """
665
    Get the Sollya expression computed from a Sage string.
666
    """
667
    return(sollya_lib_parse_string(string))
668

    
669
def pobyso_range(rnLowerBound, rnUpperBound):
670
    """ Legacy function. See pobyso_range_sa_so. """
671
    return(pobyso_range_sa_so(rnLowerBound, rnUpperBound)) 
672

    
673
def pobyso_bounds_to_range_sa_so(rnLowerBoundSa, rnUpperBoundSa):
674
    """
675
    Return a Sollya range from to 2 RealField Sage elements.
676
    The Sollya range element has a sufficient precision to hold all
677
    the digits of the Sage bounds.
678
    """
679
    # Sanity check.
680
    if rnLowerBoundSa > rnUpperBoundSa:
681
        return None
682
    # Check for the largest precision.
683
    lbPrec = rnLowerBoundSa.parent().precision()
684
    ubPrec = rnLowerBoundSa.parent().precision()
685
    currentSollyaPrecSa = pobyso_get_prec_so_sa()
686
    maxPrecSa = max(lbPrec, ubPrec, currentSollyaPrecSa)
687
    # Change the current Sollya precision only if necessary.
688
    if maxPrecSa > currentSollyaPrecSa:
689
        currentPrecSo = sollya_lib_get_prec(None)
690
        newPrecSo = solly_lib_constant_from_uint64(maxPrecSa)
691
        sollya_lib_set_prec(newPrecSo)
692
    lowerBoundSo = sollya_lib_constant(get_rn_value(rnLowerBoundSa))
693
    upperBoundSo = sollya_lib_constant(get_rn_value(rnUpperBoundSa))
694
    rangeSo = sollya_lib_range(lowerBoundSo, upperBoundSo)
695
    if maxPrecSa > currentSollyaPrecSa:
696
        sollya_lib_set_prec(currentPrecSo)
697
        sollya_lib_clear_obj(currentPrecSo)
698
        sollya_lib_clear_obj(newPrecSo)
699
    sollya_lib_clear_obj(lowerBoundSo)
700
    sollya_lib_clear_obj(upperBoundSo)
701
    return(rangeSo)
702

    
703
def pobyso_range_to_interval_so_sa(rangeSo, realIntervalField = None):
704
    """
705
    Get a Sage interval from a Sollya range.
706
    If no realIntervalField is given as a parameter, the Sage interval
707
    precision is that of the Sollya range.
708
    Otherwise, the precision is that of the realIntervalField. Rounding
709
    may happen.
710
    """
711
    if realIntervalField is None:
712
        precSa = pobyso_get_prec_of_range_so_sa(rangeSo)
713
        realIntervalField = RealIntervalField(precSa)
714
    intervalSa = \
715
        pobyso_get_interval_from_range_so_sa(rangeSo, realIntervalField) 
716
    return(intervalSa)
717

    
718
def pobyso_remez_canonical_sa_sa(func, \
719
                                 degree, \
720
                                 lowerBound, \
721
                                 upperBound, \
722
                                 weight = None, \
723
                                 quality = None):
724
    """
725
    All arguments are Sage/Python.
726
    The functions (func and weight) must be passed as expressions or strings.
727
    Otherwise the function fails. 
728
    The return value is a Sage polynomial.
729
    """
730
    var('zorglub')    # Dummy variable name for type check only. Type of 
731
    # zorglub is "symbolic expression".
732
    polySo = pobyso_remez_canonical_sa_so(func, \
733
                                 degree, \
734
                                 lowerBound, \
735
                                 upperBound, \
736
                                 weight = None, \
737
                                 quality = None)
738
    # String test
739
    if parent(func) == parent("string"):
740
        functionSa = eval(func)
741
    # Expression test.
742
    elif type(func) == type(zorglub):
743
        functionSa = func
744
    else:
745
        return None
746
    #
747
    maxPrecision = 0
748
    if polySo is None:
749
        return(None)
750
    maxPrecision = pobyso_get_max_prec_of_exp_so_sa(polySo)
751
    RRRR = RealField(maxPrecision)
752
    polynomialRing = RRRR[functionSa.variables()[0]]
753
    expSa = pobyso_get_sage_exp_from_sollya_exp_so_sa(polySo, RRRR)
754
    polySa = polynomial(expSa, polynomialRing)
755
    sollya_lib_clear_obj(polySo)
756
    return(polySa)
757
    
758
def pobyso_remez_canonical(func, \
759
                           degree, \
760
                           lowerBound, \
761
                           upperBound, \
762
                           weight = "1", \
763
                           quality = None):
764
    """ Legacy function. See pobyso_remez_canonical_sa_so. """
765
    return(pobyso_remez_canonical_sa_so(func, \
766
                                        degree, \
767
                                        lowerBound, \
768
                                        upperBound, \
769
                                        weight, \
770
                                        quality))
771
def pobyso_remez_canonical_sa_so(func, \
772
                                 degree, \
773
                                 lowerBound, \
774
                                 upperBound, \
775
                                 weight = None, \
776
                                 quality = None):
777
    """
778
    All arguments are Sage/Python.
779
    The functions (func and weight) must be passed as expressions or strings.
780
    Otherwise the function fails. 
781
    The return value is a pointer to a Sollya function.
782
    """
783
    var('zorglub')    # Dummy variable name for type check only. Type of
784
    # zorglub is "symbolic expression".
785
    currentVariableName = None
786
    # The func argument can be of different types (string, 
787
    # symbolic expression...)
788
    if parent(func) == parent("string"):
789
        functionSo = sollya_lib_parse_string(func)
790
    # Expression test.
791
    elif type(func) == type(zorglub):
792
        # Until we are able to translate Sage expressions into Sollya 
793
        # expressions : parse the string version.
794
        currentVariableName = func.variables()[0]
795
        sollya_lib_name_free_variable(str(currentVariableName))
796
        functionSo = sollya_lib_parse_string(func._assume_str())
797
    else:
798
        return(None)
799
    if weight is None:
800
        weightSo = pobyso_constant_1_sa_so()
801
    elif parent(weight) == parent("string"):
802
        weightSo = sollya_lib_parse_string(func)
803
    elif type(weight) == type(zorglub): 
804
        functionSo = sollya_lib_parse_string_sa_so(weight._assume_str())
805
    else:
806
        return(None)
807
    degreeSo = pobyso_constant_from_int(degree)
808
    rangeSo = pobyso_range_sa_so(lowerBound, upperBound)
809
    if not quality is None:
810
        qualitySo= pobyso_constant_sa_so(quality)
811
    else:
812
        qualitySo = None
813
        
814
    remezPolySo = sollya_lib_remez(functionSo, \
815
                                   degreeSo, \
816
                                   rangeSo, \
817
                                   weightSo, \
818
                                   qualitySo, \
819
                                   None)
820
    sollya_lib_clear_obj(functionSo)
821
    sollya_lib_clear_obj(degreeSo)
822
    sollya_lib_clear_obj(rangeSo)
823
    sollya_lib_clear_obj(weightSo)
824
    if not qualitySo is None:
825
        sollya_lib_clear_obj(qualtiySo)
826
    return(remezPolySo)
827
# End pobyso_remez_canonical_sa_so
828

    
829
def pobyso_remez_canonical_so_so(funcSo, \
830
                                 degreeSo, \
831
                                 rangeSo, \
832
                                 weightSo = pobyso_constant_1_sa_so(),\
833
                                 qualitySo = None):
834
    """
835
    All arguments are pointers to Sollya objects.
836
    The return value is a pointer to a Sollya function.
837
    """
838
    if not sollya_lib_obj_is_function(funcSo):
839
        return(None)
840
    return(sollya_lib_remez(funcSo, degreeSo, rangeSo, weightSo, qualitySo, None))
841
    
842
def pobyso_set_canonical_off():
843
    sollya_lib_set_canonical(sollya_lib_off())
844

    
845
def pobyso_set_canonical_on():
846
    sollya_lib_set_canonical(sollya_lib_on())
847

    
848
def pobyso_set_prec(p):
849
    """ Legacy function. See pobyso_set_prec_sa_so. """
850
    return( pobyso_set_prec_sa_so(p))
851

    
852
def pobyso_set_prec_sa_so(p):
853
    a = c_int(p)
854
    precSo = c_void_p(sollya_lib_constant_from_int(a))
855
    sollya_lib_set_prec(precSo)
856

    
857
def pobyso_supnorm_so_so(polySo, funcSo, intervalSo, errorTypeSo, accuracySo):
858
    return(sollya_lib_supnorm(polySo, funcSo, intervalSo, errorTypeSo, \
859
                              accuracySo))
860

    
861
def pobyso_taylor_expansion_with_change_var_so_so(functionSo, degreeSo, rangeSo, \
862
                                                errorTypeSo, \
863
                                                sollyaPrecSo=None):
864
    """
865
    Compute the Taylor expansion with the variable change
866
    x -> (x-intervalCenter) included.
867
    """
868
    # No global change of the working precision.
869
    if not sollyaPrecSo is None:
870
        initialPrecSo = sollya_lib_get_prec(None)
871
        sollya_lib_set_prec(sollyaPrecSo)
872
    #
873
    intervalCenterSo = sollya_lib_mid(rangeSo)
874
    taylorFormSo = sollya_lib_taylorform(functionSo, degreeSo, \
875
                                         intervalCenterSo, \
876
                                         rangeSo, errorTypeSo, None)
877
    (taylorFormListSo, numElements, isEndElliptic) = \
878
        pobyso_get_list_elements_so_so(taylorFormSo)
879
    polySo = taylorFormListSo[0]
880
    errorRangeSo = taylorFormListSo[2]
881
    maxErrorSo = sollya_lib_sup(errorRangeSo)
882
    changeVarExpSo = sollya_lib_build_function_sub(\
883
                       sollya_lib_build_function_free_variable(),\
884
                       sollya_lib_copy_obj(intervalCenterSo))
885
    polyVarChangedSo = sollya_lib_evaluate(polySo, changeVarExpSo) 
886
    # If changed, reset the Sollya working precision.
887
    if not sollyaPrecSo is None:
888
        sollya_lib_set_prec(initialPrecSo)
889
        sollya_lib_clear_obj(initialPrecSo)
890
    return((polyVarChangedSo, intervalCenterSo, maxErrorSo))
891
# end pobyso_taylor_expansion_with_change_var_so_so
892

    
893
def pobyso_taylor_expansion_no_change_var_so_so(functionSo, degreeSo, rangeSo, \
894
                                                errorTypeSo, \
895
                                                sollyaPrecSo=None):
896
    """
897
    Compute the Taylor expansion without the variable change
898
    x -> x-intervalCenter.
899
    """
900
    # No global change of the working precision.
901
    if not sollyaPrecSo is None:
902
        initialPrecSo = sollya_lib_get_prec(None)
903
        sollya_lib_set_prec(sollyaPrecSo)
904
    #
905
    intervalCenterSo = sollya_lib_mid(rangeSo)
906
    taylorFormSo = sollya_lib_taylorform(functionSo, degreeSo, \
907
                                         intervalCenterSo, \
908
                                         rangeSo, errorTypeSo, None)
909
    (taylorFormListSo, numElements, isEndElliptic) = \
910
        pobyso_get_list_elements_so_so(taylorFormSo)
911
    polySo = taylorFormListSo[0]
912
    errorRangeSo = taylorFormListSo[2]
913
    maxErrorSo = sollya_lib_sup(errorRangeSo)
914
    # If changed, reset the Sollya working precision.
915
    if not sollyaPrecSo is None:
916
        sollya_lib_set_prec(initialPrecSo)
917
        sollya_lib_clear_obj(initialPrecSo)
918
    return((polySo, intervalCenterSo, maxErrorSo))
919
# end pobyso_taylor_expansion_no_change_var_so_so
920

    
921
def pobyso_taylor(function, degree, point):
922
    """ Legacy function. See pobysoTaylor_so_so. """
923
    return(pobyso_taylor_so_so(function, degree, point))
924

    
925
def pobyso_taylor_so_so(functionSo, degreeSo, pointSo):
926
    return(sollya_lib_taylor(functionSo, degreeSo, pointSo))
927
    
928
def pobyso_taylorform(function, degree, point = None, interval = None, errorType=None):
929
    """ Legacy function. See ;"""
930
    
931
def pobyso_taylorform_sa_sa(functionSa, \
932
                            degree, \
933
                            point, \
934
                            precision, \
935
                            interval=None, \
936
                            errorType=None):
937
    """
938
    Compute the Taylor form of 'degree' for 'functionSa' at 'point' 
939
    for 'interval' with 'errorType'. 
940
    point: must be a Real or a Real interval.
941
    return the Taylor form as an array
942
    TODO: take care of the interval and of the point when it is an interval;
943
          when errorType is not None;
944
          take care of the other elements of the Taylor form (coefficients 
945
          errors and delta.
946
    """
947
    # Absolute as the default error.
948
    if errorType is None:
949
        errorTypeSo = sollya_lib_absolute()
950
    else:
951
        #TODO: deal with the other case.
952
        pass
953
    varSa = functionSa.variables()[0]
954
    pointBaseRingString = str(point.base_ring())
955
    if not re.search('Real', pointBaseRingString):
956
        return None
957
    # Call Sollya but first "sollyafy" the arguments.
958
    pobyso_name_free_variable_sa_so(str(varSa))
959
    #pobyso_set_prec_sa_so(300)
960
    # Sollyafy the function.
961
    functionSo = pobyso_parse_string_sa_so(functionSa._assume_str())
962
    if sollya_lib_obj_is_error(functionSo):
963
        print "pobyso_tailorform: function string can't be parsed!"
964
        return None
965
    # Sollyafy the degree
966
    degreeSo = sollya_lib_constant_from_int(int(degree))
967
    # Sollyafy the point
968
    if not re.search('Interval', pointBaseRingString):
969
        pointSo  = pobyso_constant_sa_so(point)
970
    else:
971
        # TODO: deal with the interval case.
972
        pass
973
    # Call Sollya
974
    taylorFormSo = \
975
        sollya_lib_taylorform(functionSo, degreeSo, pointSo, errorTypeSo,\
976
                                         None)
977
    (tfsAsList, numElements, isEndElliptic) = \
978
            pobyso_get_list_elements_so_so(taylorFormSo)
979
    polySo = tfsAsList[0]
980
    maxPrecision = pobyso_get_max_prec_of_exp_so_sa(polySo)
981
    polyRealField = RealField(maxPrecision)
982
    expSa = pobyso_get_sage_exp_from_sollya_exp_so_sa(polySo, polyRealField)
983
    sollya_lib_close()
984
    polynomialRing = polyRealField[str(varSa)]
985
    polySa = polynomial(expSa, polynomialRing)
986
    taylorFormSa = [polySa]
987
    return(taylorFormSa)
988
# End pobyso_taylor_form_sa_sa
989

    
990
def pobyso_taylorform_so_so(functionSo, degreeSo, pointSo, intervalSo=None, \
991
                            errorTypeSo=None):
992
    createdErrorType = False
993
    if errorTypeSo is None:
994
        errorTypeSo = sollya_lib_absolute()
995
        createdErrorType = True
996
    else:
997
        #TODO: deal with the other case.
998
        pass
999
    if intervalSo is None:
1000
        resultSo = sollya_lib_taylorform(functionSo, degreeSo, pointSo, \
1001
                                         errorTypeSo, None)
1002
    else:
1003
        resultSo = sollya_lib_taylorform(functionSo, degreeSo, pointSo, \
1004
                                         intervalSo, errorTypeSo, None)
1005
    if createdErrorType:
1006
        sollya_lib_clear_obj(errorTypeSo)
1007
    return(resultSo)
1008
        
1009

    
1010
def pobyso_univar_polynomial_print_reverse(polySa):
1011
    """ Legacy function. See pobyso_univar_polynomial_print_reverse_sa_sa. """
1012
    return(pobyso_univar_polynomial_print_reverse_sa_sa(polySa))
1013

    
1014
def pobyso_univar_polynomial_print_reverse_sa_sa(polySa):
1015
    """
1016
    Return the string representation of a univariate polynomial with
1017
    monomials ordered in the x^0..x^n order of the monomials.
1018
    Remember: Sage
1019
    """
1020
    polynomialRing = polySa.base_ring()
1021
    # A very expensive solution:
1022
    # -create a fake multivariate polynomial field with only one variable,
1023
    #   specifying a negative lexicographical order;
1024
    mpolynomialRing = PolynomialRing(polynomialRing.base(), \
1025
                                     polynomialRing.variable_name(), \
1026
                                     1, order='neglex')
1027
    # - convert the univariate argument polynomial into a multivariate
1028
    #   version;
1029
    p = mpolynomialRing(polySa)
1030
    # - return the string representation of the converted form.
1031
    # There is no simple str() method defined for p's class.
1032
    return(p.__str__())
1033
#
1034
print pobyso_get_prec()  
1035
pobyso_set_prec(165)
1036
print pobyso_get_prec()  
1037
a=100
1038
print type(a)
1039
id(a)
1040
print "Max arity: ", pobyso_max_arity
1041
print "Function tripleDouble (43) as a string: ", pobyso_function_type_as_string(43)
1042
print "Function None (44) as a string: ", pobyso_function_type_as_string(44)
1043
print "...Pobyso check done"