Statistiques
| Révision :

root / pobysoPythonSage / src / pobyso.py @ 179

Historique | Voir | Annoter | Télécharger (51,75 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_absolute_so_so():
89
    return(sollya_lib_absolute(None))
90

    
91
def pobyso_autoprint(arg):
92
    sollya_lib_autoprint(arg,None)
93

    
94
def pobyso_autoprint_so_so(arg):
95
    sollya_lib_autoprint(arg,None)
96
    
97
def pobyso_bounds_to_range_sa_so(rnLowerBoundSa, rnUpperBoundSa, \
98
                                 precisionSa=None):
99
    """
100
    Return a Sollya range from to 2 RealField Sage elements.
101
    The Sollya range element has a sufficient precision to hold all
102
    the digits of the widest of the Sage bounds.
103
    """
104
    # Sanity check.
105
    if rnLowerBoundSa > rnUpperBoundSa:
106
        return None
107
    # Precision stuff.
108
    if precisionSa is None:
109
        # Check for the largest precision.
110
        lbPrecSa = rnLowerBoundSa.parent().precision()
111
        ubPrecSa = rnLowerBoundSa.parent().precision()
112
        maxPrecSa = max(lbPrecSa, ubPrecSa)
113
    else:
114
        maxPrecSa = precisionSa
115
    # From Sage to Sollya bounds.
116
#    lowerBoundSo = sollya_lib_constant(get_rn_value(rnLowerBoundSa),
117
#                                       maxPrecSa)
118
    lowerBoundSo = pobyso_constant_sa_so(rnLowerBoundSa,
119
                                         maxPrecSa)
120
    upperBoundSo = pobyso_constant_sa_so(rnUpperBoundSa,
121
                                       maxPrecSa)
122
    
123
    # From Sollya bounds to range.
124
    rangeSo = sollya_lib_range(lowerBoundSo, upperBoundSo)
125
    # Back to original precision.
126
    # Clean up
127
    sollya_lib_clear_obj(lowerBoundSo)
128
    sollya_lib_clear_obj(upperBoundSo)
129
    return rangeSo
130
# End pobyso_bounds_to_range_sa_so
131

    
132
def pobyso_build_function_sub_so_so(exp1So, exp2So):
133
    return(sollya_lib_build_function_sub(exp1So, exp2So))
134

    
135
def pobyso_change_var_in_function_so_so(funcSo, chvarExpSo):
136
    """
137
    Variable change in a function.
138
    """
139
    return(sollya_lib_evaluate(funcSo,chvarExpSo))
140
# End pobyso_change_var_in_function_so_so     
141

    
142
def pobyso_chebyshevform_so_so(functionSo, degreeSo, intervalSo):
143
    resultSo = sollya_lib_chebyshevform(functionSo, degreeSo, intervalSo)
144
    return(resultSo)
145
# End pobyso_chebyshevform_so_so.
146

    
147
def pobyso_clear_taylorform_sa_so(taylorFormSaSo):
148
    """
149
    This method is necessary to correctly clean up the memory from Taylor forms.
150
    These are made of a Sollya object, a Sollya object list, a Sollya object.
151
    For no clearly understood reason, sollya_lib_clear_object_list crashed 
152
    when applied to the object list.
153
    Here, we decompose it into Sage list of Sollya objects references and we
154
     clear them one by one. 
155
    """
156
    sollya_lib_clear_obj(taylorFormSaSo[0])
157
    (coefficientsErrorsListSaSo, numElementsSa, isEndEllipticSa) = \
158
        pobyso_get_list_elements_so_so(taylorFormSaSo[1])
159
    for element in coefficientsErrorsListSaSo:
160
        sollya_lib_clear_obj(element)
161
    sollya_lib_clear_obj(taylorFormSaSo[1])
162
    sollya_lib_clear_obj(taylorFormSaSo[2])
163
# End pobyso_clear_taylorform_sa_so 
164

    
165
def pobyso_cmp(rnArgSa, cteSo):
166
    """
167
    Compare the MPFR value a RealNumber with that of a Sollya constant.
168
    
169
    Get the value of the Sollya constant into a RealNumber and compare
170
    using MPFR. Could be optimized by working directly with a mpfr_t
171
    for the intermediate number. 
172
    """
173
    # Get the precision of the Sollya constant to build a Sage RealNumber 
174
    # with enough precision.to hold it.
175
    precisionOfCte = c_int(0)
176
    # From the Sollya constant, create a local Sage RealNumber.
177
    sollya_lib_get_prec_of_constant(precisionOfCte, cteSo) 
178
    #print "Precision of constant: ", precisionOfCte
179
    RRRR = RealField(precisionOfCte.value)
180
    rnLocalSa = RRRR(0)
181
    sollya_lib_get_constant(get_rn_value(rnLocalSa), cteSo)
182
    #
183
    ## Compare the Sage RealNumber version of the Sollya constant with rnArg.
184
    return(cmp_rn_value(rnArgSa, rnLocal))
185
# End pobyso_smp
186

    
187
def pobyso_compute_pos_function_abs_val_bounds_sa_sa(funcSa, lowerBoundSa, \
188
                                                     upperBoundSa):
189
    """
190
    TODO: completely rework and test.
191
    """
192
    pobyso = pobyso_name_free_variable_sa_so(funcSa.variables()[0])
193
    funcSo = pobyso_parse_string(funcSa._assume_str().replace('_SAGE_VAR_', ''))
194
    rangeSo = pobyso_range_sa_so(lowerBoundSa, upperBoundSa)
195
    infnormSo = pobyso_infnorm_so_so(funcSo,rangeSo)
196
    # Sollya return the infnorm as an interval.
197
    fMaxSa = pobyso_get_interval_from_range_so_sa(infnormSo)
198
    # Get the top bound and compute the binade top limit.
199
    fMaxUpperBoundSa = fMaxSa.upper()
200
    binadeTopLimitSa = 2**ceil(fMaxUpperBoundSa.log2())
201
    # Put up together the function to use to compute the lower bound.
202
    funcAuxSo = pobyso_parse_string(str(binadeTopLimitSa) +  \
203
                                    '-(' + f._assume_str().replace('_SAGE_VAR_', '') + ')')
204
    pobyso_autoprint(funcAuxSo)
205
    # Clear the Sollya range before a new call to infnorm and issue the call.
206
    sollya_lib_clear_obj(infnormSo)
207
    infnormSo = pobyso_infnorm_so_so(funcAuxSo,rangeSo)
208
    fMinSa = pobyso_get_interval_from_range_so_sa(infnormSo)
209
    sollya_lib_clear_obj(infnormSo)
210
    fMinLowerBoundSa = binadeTopLimitSa - fMinSa.lower()
211
    # Compute the maximum of the precisions of the different bounds.
212
    maxPrecSa = max([fMinLowerBoundSa.parent().precision(), \
213
                     fMaxUpperBoundSa.parent().precision()])
214
    # Create a RealIntervalField and create an interval with the "good" bounds.
215
    RRRI = RealIntervalField(maxPrecSa)
216
    imageIntervalSa = RRRI(fMinLowerBoundSa, fMaxUpperBoundSa)
217
    # Free the unneeded Sollya objects
218
    sollya_lib_clear_obj(funcSo)
219
    sollya_lib_clear_obj(funcAuxSo)
220
    sollya_lib_clear_obj(rangeSo)
221
    return(imageIntervalSa)
222
# End pobyso_compute_pos_function_abs_val_bounds_sa_sa
223

    
224
def pobyso_constant(rnArg):
225
    """ Legacy function. See pobyso_constant_sa_so. """
226
    return(pobyso_constant_sa_so(rnArg))
227
    
228
def pobyso_constant_sa_so(rnArgSa, precisionSa=None):
229
    """
230
    Create a Sollya constant from a Sage RealNumber.
231
    """
232
    # Precision stuff
233
    if precisionSa is None:
234
        precisionSa = rnArgSa.parent().precision()
235
    currentSollyaPrecisionSo = sollya_lib_get_prec()
236
    currentSollyaPrecisionSa = \
237
        pobyso_constant_from_int(currentSollyaPrecisionSo)
238
    # Sollya constant creation takes place here.
239
    if precisionSa > currentSollyaPrecisionSa:
240
        pobyso_set_prec_sa_so(precisionSa)
241
        constantSo = sollya_lib_constant(get_rn_value(rnArgSa))
242
        pobyso_set_prec_so_so(currentSollyaPrecisionSo)
243
    else:
244
        constantSo = sollya_lib_constant(get_rn_value(rnArgSa))
245
    sollya_lib_clear_obj(currentSollyaPrecisionSo)
246
    return constantSo
247
# End pobyso_constant_sa_so
248
     
249
def pobyso_constant_0_sa_so():
250
    """
251
    Obvious.
252
    """
253
    return(pobyso_constant_from_int_sa_so(0))
254

    
255
def pobyso_constant_1():
256
    """
257
    Obvious.
258
    Legacy function. See pobyso_constant_so_so. 
259
    """
260
    return(pobyso_constant_1_sa_so())
261

    
262
def pobyso_constant_1_sa_so():
263
    """
264
    Obvious.
265
    """
266
    return(pobyso_constant_from_int_sa_so(1))
267

    
268
def pobyso_constant_from_int(anInt):
269
    """ Legacy function. See pobyso_constant_from_int_sa_so. """
270
    return(pobyso_constant_from_int_sa_so(anInt))
271

    
272
def pobyso_constant_from_int_sa_so(anInt):
273
    """
274
    Get a Sollya constant from a Sage int.
275
    """
276
    return(sollya_lib_constant_from_int(int(anInt)))
277

    
278
def pobyso_constant_from_int_so_sa(constSo):
279
    """
280
    Get a Sage int from a Sollya int constant.
281
    Usefull for precision or powers in polynomials.
282
    """
283
    constSa = c_int(0)
284
    sollya_lib_get_constant_as_int(byref(constSa), constSo)
285
    return(constSa.value)
286
# End pobyso_constant_from_int_so_sa
287

    
288
def pobyso_error_so():
289
    return sollya_lib_error(None)
290
# End pobyso_error().
291

    
292
def pobyso_function_type_as_string(funcType):
293
    """ Legacy function. See pobyso_function_type_as_string_so_sa. """
294
    return(pobyso_function_type_as_string_so_sa(funcType))
295

    
296
def pobyso_function_type_as_string_so_sa(funcType):
297
    """
298
    Numeric Sollya function codes -> Sage mathematical function names.
299
    Notice that pow -> ^ (a la Sage, not a la Python).
300
    """
301
    if funcType == SOLLYA_BASE_FUNC_ABS:
302
        return "abs"
303
    elif funcType == SOLLYA_BASE_FUNC_ACOS:
304
        return "arccos"
305
    elif funcType == SOLLYA_BASE_FUNC_ACOSH:
306
        return "arccosh"
307
    elif funcType == SOLLYA_BASE_FUNC_ADD:
308
        return "+"
309
    elif funcType == SOLLYA_BASE_FUNC_ASIN:
310
        return "arcsin"
311
    elif funcType == SOLLYA_BASE_FUNC_ASINH:
312
        return "arcsinh"
313
    elif funcType == SOLLYA_BASE_FUNC_ATAN:
314
        return "arctan"
315
    elif funcType == SOLLYA_BASE_FUNC_ATANH:
316
        return "arctanh"
317
    elif funcType == SOLLYA_BASE_FUNC_CEIL:
318
        return "ceil"
319
    elif funcType == SOLLYA_BASE_FUNC_CONSTANT:
320
        return "cte"
321
    elif funcType == SOLLYA_BASE_FUNC_COS:
322
        return "cos"
323
    elif funcType == SOLLYA_BASE_FUNC_COSH:
324
        return "cosh"
325
    elif funcType == SOLLYA_BASE_FUNC_DIV:
326
        return "/"
327
    elif funcType == SOLLYA_BASE_FUNC_DOUBLE:
328
        return "double"
329
    elif funcType == SOLLYA_BASE_FUNC_DOUBLEDOUBLE:
330
        return "doubleDouble"
331
    elif funcType == SOLLYA_BASE_FUNC_DOUBLEEXTENDED:
332
        return "doubleDxtended"
333
    elif funcType == SOLLYA_BASE_FUNC_ERF:
334
        return "erf"
335
    elif funcType == SOLLYA_BASE_FUNC_ERFC:
336
        return "erfc"
337
    elif funcType == SOLLYA_BASE_FUNC_EXP:
338
        return "exp"
339
    elif funcType == SOLLYA_BASE_FUNC_EXP_M1:
340
        return "expm1"
341
    elif funcType == SOLLYA_BASE_FUNC_FLOOR:
342
        return "floor"
343
    elif funcType == SOLLYA_BASE_FUNC_FREE_VARIABLE:
344
        return "freeVariable"
345
    elif funcType == SOLLYA_BASE_FUNC_HALFPRECISION:
346
        return "halfPrecision"
347
    elif funcType == SOLLYA_BASE_FUNC_LIBRARYCONSTANT:
348
        return "libraryConstant"
349
    elif funcType == SOLLYA_BASE_FUNC_LIBRARYFUNCTION:
350
        return "libraryFunction"
351
    elif funcType == SOLLYA_BASE_FUNC_LOG:
352
        return "log"
353
    elif funcType == SOLLYA_BASE_FUNC_LOG_10:
354
        return "log10"
355
    elif funcType == SOLLYA_BASE_FUNC_LOG_1P:
356
        return "log1p"
357
    elif funcType == SOLLYA_BASE_FUNC_LOG_2:
358
        return "log2"
359
    elif funcType == SOLLYA_BASE_FUNC_MUL:
360
        return "*"
361
    elif funcType == SOLLYA_BASE_FUNC_NEARESTINT:
362
        return "round"
363
    elif funcType == SOLLYA_BASE_FUNC_NEG:
364
        return "__neg__"
365
    elif funcType == SOLLYA_BASE_FUNC_PI:
366
        return "pi"
367
    elif funcType == SOLLYA_BASE_FUNC_POW:
368
        return "^"
369
    elif funcType == SOLLYA_BASE_FUNC_PROCEDUREFUNCTION:
370
        return "procedureFunction"
371
    elif funcType == SOLLYA_BASE_FUNC_QUAD:
372
        return "quad"
373
    elif funcType == SOLLYA_BASE_FUNC_SIN:
374
        return "sin"
375
    elif funcType == SOLLYA_BASE_FUNC_SINGLE:
376
        return "single"
377
    elif funcType == SOLLYA_BASE_FUNC_SINH:
378
        return "sinh"
379
    elif funcType == SOLLYA_BASE_FUNC_SQRT:
380
        return "sqrt"
381
    elif funcType == SOLLYA_BASE_FUNC_SUB:
382
        return "-"
383
    elif funcType == SOLLYA_BASE_FUNC_TAN:
384
        return "tan"
385
    elif funcType == SOLLYA_BASE_FUNC_TANH:
386
        return "tanh"
387
    elif funcType == SOLLYA_BASE_FUNC_TRIPLEDOUBLE:
388
        return "tripleDouble"
389
    else:
390
        return None
391

    
392
def pobyso_get_constant(rnArgSa, constSo):
393
    """ Legacy function. See pobyso_get_constant_so_sa. """
394
    return(pobyso_get_constant_so_sa(rnArgSa, constSo))
395

    
396
def pobyso_get_constant_so_sa(rnArgSa, constSo):
397
    """
398
    Set the value of rnArgSo to the value of constSo in MPFR_RNDN mode.
399
    rnArg must already exist and belong to some RealField.
400
    We assume that constSo points to a Sollya constant.
401
    """
402
    return(sollya_lib_get_constant(get_rn_value(rnArgSa), constSo))
403
    
404
def pobyso_get_constant_as_rn(ctExpSo):
405
    """ 
406
    Legacy function. See pobyso_get_constant_as_rn_so_sa. 
407
    """ 
408
    return(pobyso_get_constant_as_rn_so_sa(ctExpSo))
409
    
410
def pobyso_get_constant_as_rn_so_sa(constExpSo):
411
    """
412
    Get a Sollya constant as a Sage "real number".
413
    The precision of the floating-point number returned is that of the Sollya
414
    constant.
415
    """
416
    precisionSa  = pobyso_get_prec_of_constant_so_sa(constExpSo) 
417
    RRRR = RealField(precisionSa)
418
    rnSa = RRRR(0)
419
    sollya_lib_get_constant(get_rn_value(rnSa), constExpSo)
420
    return(rnSa)
421
# End pobyso_get_constant_as_rn_so_sa
422

    
423
def pobyso_get_constant_as_rn_with_rf(ctExp, realField):
424
    """ 
425
    Legacy function. See pobyso_get_constant_as_rn_with_rf_so_sa.
426
    """
427
    return(pobyso_get_constant_as_rn_with_rf_so_sa(ctExp, realField))
428
    
429
def pobyso_get_constant_as_rn_with_rf_so_sa(ctExpSo, realFieldSa = None):
430
    """
431
    Get a Sollya constant as a Sage "real number".
432
    If no real field is specified, the precision of the floating-point number 
433
    returned is that of the Sollya constant.
434
    Otherwise is is that of the real field. Hence rounding may happen.
435
    """
436
    if realFieldSa is None:
437
        sollyaPrecSa = pobyso_get_prec_of_constant_so_sa(ctExpSo)
438
        realFieldSa = RealField(sollyaPrecSa)
439
    rnSa = realFieldSa(0)
440
    sollya_lib_get_constant(get_rn_value(rnSa), ctExpSo)
441
    return(rnSa)
442
# End pobyso_get_constant_as_rn_with_rf_so_sa
443

    
444
def pobyso_get_free_variable_name():
445
    """ 
446
    Legacy function. See pobyso_get_free_variable_name_so_sa.
447
    """
448
    return(pobyso_get_free_variable_name_so_sa())
449

    
450
def pobyso_get_free_variable_name_so_sa():
451
    return(sollya_lib_get_free_variable_name())
452
    
453
def pobyso_get_function_arity(expressionSo):
454
    """ 
455
    Legacy function. See pobyso_get_function_arity_so_sa.
456
    """
457
    return(pobyso_get_function_arity_so_sa(expressionSo))
458

    
459
def pobyso_get_function_arity_so_sa(expressionSo):
460
    arity = c_int(0)
461
    sollya_lib_get_function_arity(byref(arity),expressionSo)
462
    return(int(arity.value))
463

    
464
def pobyso_get_head_function(expressionSo):
465
    """ 
466
    Legacy function. See pobyso_get_head_function_so_sa. 
467
    """
468
    return(pobyso_get_head_function_so_sa(expressionSo)) 
469

    
470
def pobyso_get_head_function_so_sa(expressionSo):
471
    functionType = c_int(0)
472
    sollya_lib_get_head_function(byref(functionType), expressionSo, None)
473
    return(int(functionType.value))
474

    
475
def pobyso_get_interval_from_range_so_sa(soRange, realIntervalFieldSa = None ):
476
    """
477
    Return the Sage interval corresponding to the Sollya range argument.
478
    If no reaIntervalField is passed as an argument, the interval bounds are not
479
    rounded: they are elements of RealIntervalField of the "right" precision
480
    to hold all the digits.
481
    """
482
    prec = c_int(0)
483
    if realIntervalFieldSa is None:
484
        retval = sollya_lib_get_prec_of_range(byref(prec), soRange, None)
485
        if retval == 0:
486
            return(None)
487
        realIntervalFieldSa = RealIntervalField(prec.value)
488
    intervalSa = realIntervalFieldSa(0,0)
489
    retval = \
490
        sollya_lib_get_interval_from_range(get_interval_value(intervalSa),\
491
                                           soRange)
492
    if retval == 0:
493
        return(None)
494
    return(intervalSa)
495
# End pobyso_get_interval_from_range_so_sa
496

    
497
def pobyso_get_list_elements(soObj):
498
    """ Legacy function. See pobyso_get_list_elements_so_so. """
499
    return(pobyso_get_list_elements_so_so(soObj))
500
 
501
def pobyso_get_list_elements_so_so(objectListSo):
502
    """
503
    Get the Sollya list elements as a Sage/Python array of Sollya objects.
504
    
505
    INPUT:
506
    - objectListSo: a Sollya list of Sollya objects.
507
    
508
    OUTPUT:
509
    - a Sage/Python tuple made of:
510
      - a Sage/Python list of Sollya objects,
511
      - a Sage/Python int holding the number of elements,
512
      - a Sage/Python int stating (!= 0) that the list is end-elliptic.
513
    NOTE::
514
        We recover the addresses of the Sollya object from the list of pointers
515
        returned by sollya_lib_get_list_elements. The list itself is freed.
516
    TODO::
517
        Figure out what to do with numElements since the number of elements
518
        can easily be recovered from the list itself. 
519
        Ditto for isEndElliptic.
520
    """
521
    listAddress = POINTER(c_longlong)()
522
    numElements = c_int(0)
523
    isEndElliptic = c_int(0)
524
    listAsSageList = []
525
    result = sollya_lib_get_list_elements(byref(listAddress),\
526
                                          byref(numElements),\
527
                                          byref(isEndElliptic),\
528
                                          objectListSo)
529
    if result == 0 :
530
        return None
531
    for i in xrange(0, numElements.value, 1):
532
       #listAsSageList.append(sollya_lib_copy_obj(listAddress[i]))
533
       listAsSageList.append(listAddress[i])
534
       # Clear each of the elements returned by Sollya.
535
       #sollya_lib_clear_obj(listAddress[i])
536
    # Free the list itself.   
537
    sollya_lib_free(listAddress)
538
    return(listAsSageList, numElements.value, isEndElliptic.value)
539

    
540
def pobyso_get_max_prec_of_exp(soExp):
541
    """ Legacy function. See pobyso_get_max_prec_of_exp_so_sa. """
542
    return(pobyso_get_max_prec_of_exp_so_sa(soExp))
543

    
544
def pobyso_get_max_prec_of_exp_so_sa(expSo):
545
    """
546
    Get the maximum precision used for the numbers in a Sollya expression.
547
    
548
    Arguments:
549
    soExp -- a Sollya expression pointer
550
    Return value:
551
    A Python integer
552
    TODO: 
553
    - error management;
554
    - correctly deal with numerical type such as DOUBLEEXTENDED.
555
    """
556
    maxPrecision = 0
557
    minConstPrec = 0
558
    currentConstPrec = 0
559
    operator = pobyso_get_head_function_so_sa(expSo)
560
    if (operator != SOLLYA_BASE_FUNC_CONSTANT) and \
561
    (operator != SOLLYA_BASE_FUNC_FREE_VARIABLE):
562
        (arity, subexpressions) = pobyso_get_subfunctions_so_sa(expSo)
563
        for i in xrange(arity):
564
            maxPrecisionCandidate = \
565
                pobyso_get_max_prec_of_exp_so_sa(subexpressions[i])
566
            if maxPrecisionCandidate > maxPrecision:
567
                maxPrecision = maxPrecisionCandidate
568
        return(maxPrecision)
569
    elif operator == SOLLYA_BASE_FUNC_CONSTANT:
570
        #minConstPrec = pobyso_get_min_prec_of_constant_so_sa(expSo)
571
        #currentConstPrec = pobyso_get_min_prec_of_constant_so_sa(soExp)
572
        #print minConstPrec, " - ", currentConstPrec 
573
        return(pobyso_get_min_prec_of_constant_so_sa(expSo))
574
    
575
    elif operator == SOLLYA_BASE_FUNC_FREE_VARIABLE:
576
        return(0)
577
    else:
578
        print "pobyso_get_max_prec_of_exp_so_sa: unexepected operator."
579
        return(0)
580

    
581
def pobyso_get_min_prec_of_constant_so_sa(constExpSo):
582
    """
583
    Get the minimum precision necessary to represent the value of a Sollya
584
    constant.
585
    MPFR_MIN_PREC and powers of 2 are taken into account.
586
    We assume that constExpSo is a point
587
    """
588
    constExpAsRnSa = pobyso_get_constant_as_rn_so_sa(constExpSo)
589
    return(min_mpfr_size(get_rn_value(constExpAsRnSa)))
590

    
591
def pobyso_get_sage_exp_from_sollya_exp(sollyaExpSo, realField = RR):
592
    """ Legacy function. See pobyso_get_sage_exp_from_sollya_exp_so_sa. """
593
    return(pobyso_get_sage_exp_from_sollya_exp_so_sa(sollyaExpSo, \
594
                                                     realField = RR))
595

    
596
def pobyso_get_sage_exp_from_sollya_exp_so_sa(sollyaExpSo, realFieldSa = RR):
597
    """
598
    Get a Sage expression from a Sollya expression. 
599
    Currently only tested with polynomials with floating-point coefficients.
600
    Notice that, in the returned polynomial, the exponents are RealNumbers.
601
    """
602
    #pobyso_autoprint(sollyaExp)
603
    operatorSa = pobyso_get_head_function_so_sa(sollyaExpSo)
604
    sollyaLibFreeVariableName = sollya_lib_get_free_variable_name()
605
    # Constants and the free variable are special cases.
606
    # All other operator are dealt with in the same way.
607
    if (operatorSa != SOLLYA_BASE_FUNC_CONSTANT) and \
608
       (operatorSa != SOLLYA_BASE_FUNC_FREE_VARIABLE):
609
        (aritySa, subexpressionsSa) = pobyso_get_subfunctions_so_sa(sollyaExpSo)
610
        if aritySa == 1:
611
            sageExpSa = eval(pobyso_function_type_as_string_so_sa(operatorSa) + \
612
            "(" + pobyso_get_sage_exp_from_sollya_exp_so_sa(subexpressionsSa[0], \
613
            realFieldSa) + ")")
614
        elif aritySa == 2:
615
            # We do not get through the preprocessor.
616
            # The "^" operator is then a special case.
617
            if operatorSa == SOLLYA_BASE_FUNC_POW:
618
                operatorAsStringSa = "**"
619
            else:
620
                operatorAsStringSa = \
621
                    pobyso_function_type_as_string_so_sa(operatorSa)
622
            sageExpSa = \
623
              eval("pobyso_get_sage_exp_from_sollya_exp_so_sa(subexpressionsSa[0], realFieldSa)"\
624
              + " " + operatorAsStringSa + " " + \
625
                   "pobyso_get_sage_exp_from_sollya_exp_so_sa(subexpressionsSa[1], realFieldSa)")
626
        # We do not know yet how to deal with arity >= 3 
627
        # (is there any in Sollya anyway?).
628
        else:
629
            sageExpSa = eval('None')
630
        return(sageExpSa)
631
    elif operatorSa == SOLLYA_BASE_FUNC_CONSTANT:
632
        #print "This is a constant"
633
        return pobyso_get_constant_as_rn_with_rf_so_sa(sollyaExpSo, realFieldSa)
634
    elif operatorSa == SOLLYA_BASE_FUNC_FREE_VARIABLE:
635
        #print "This is free variable"
636
        return(eval(sollyaLibFreeVariableName))
637
    else:
638
        print "Unexpected"
639
        return eval('None')
640
# End pobyso_get_sage_poly_from_sollya_poly
641

    
642
def pobyso_get_poly_sa_so(polySo, realFieldSa=None):
643
    """
644
    Create a Sollya polynomial from a Sage polynomial.
645
    """
646
    pass
647
# pobyso_get_poly_sa_so
648

    
649
def pobyso_get_poly_so_sa(polySo, realFieldSa=None):
650
    """
651
    Convert a Sollya polynomial into a Sage polynomial.
652
    We assume that the polynomial is in canonical form.
653
    If no realField is given, a RealField corresponding to the maximum 
654
    precision of the coefficients is internally computed.
655
    The real field is not returned but can be easily retrieved from 
656
    the polynomial itself.
657
    ALGORITHM:
658
    - (optional) compute the RealField of the coefficients;
659
    - convert the Sollya expression into a Sage expression;
660
    - convert the Sage expression into a Sage polynomial
661
    TODO: the canonical thing for the polynomial.
662
    """    
663
    if realFieldSa is None:
664
        expressionPrecSa = pobyso_get_max_prec_of_exp_so_sa(polySo)
665
        realFieldSa = RealField(expressionPrecSa)
666
    #print "Sollya expression before...",
667
    #pobyso_autoprint(polySo)
668

    
669
    expressionSa = pobyso_get_sage_exp_from_sollya_exp_so_sa(polySo, \
670
                                                             realFieldSa)
671
    #print "...Sollya expression after.",
672
    #pobyso_autoprint(polySo)
673
    polyVariableSa = expressionSa.variables()[0]
674
    polyRingSa = realFieldSa[str(polyVariableSa)]
675
    #print polyRingSa
676
    # Do not use the polynomial(expressionSa, ring=polyRingSa) form!
677
    polynomialSa = polyRingSa(expressionSa)
678
    return(polynomialSa)
679
# End pobyso_get_sage_poly_from_sollya_poly
680

    
681
def pobyso_get_subfunctions(expressionSo):
682
    """ Legacy function. See pobyso_get_subfunctions_so_sa. """
683
    return(pobyso_get_subfunctions_so_sa(expressionSo)) 
684

    
685
def pobyso_get_subfunctions_so_sa(expressionSo):
686
    """
687
    Get the subfunctions of an expression.
688
    Return the number of subfunctions and the list of subfunctions addresses.
689
    S.T.: Could not figure out another way than that ugly list of declarations
690
    to recover the addresses of the subfunctions.
691
    We limit ourselves to arity 8 functions. 
692
    """
693
    subf0 = c_int(0)
694
    subf1 = c_int(0)
695
    subf2 = c_int(0)
696
    subf3 = c_int(0)
697
    subf4 = c_int(0)
698
    subf5 = c_int(0)
699
    subf6 = c_int(0)
700
    subf7 = c_int(0)
701
    subf8 = c_int(0)
702
    arity = c_int(0)
703
    nullPtr = POINTER(c_int)()
704
    sollya_lib_get_subfunctions(expressionSo, byref(arity), \
705
      byref(subf0), byref(subf1), byref(subf2), byref(subf3), \
706
      byref(subf4), byref(subf5),\
707
      byref(subf6), byref(subf7), byref(subf8), nullPtr, None) 
708
#    byref(cast(subfunctions[0], POINTER(c_int))), \
709
#    byref(cast(subfunctions[0], POINTER(c_int))), \
710
#    byref(cast(subfunctions[2], POINTER(c_int))), \
711
#    byref(cast(subfunctions[3], POINTER(c_int))), \
712
#    byref(cast(subfunctions[4], POINTER(c_int))), \
713
#    byref(cast(subfunctions[5], POINTER(c_int))), \
714
#    byref(cast(subfunctions[6], POINTER(c_int))), \
715
#    byref(cast(subfunctions[7], POINTER(c_int))), \
716
#    byref(cast(subfunctions[8], POINTER(c_int))), nullPtr)
717
    subfunctions = [subf0, subf1, subf2, subf3, subf4, subf5, subf6, subf7, \
718
                    subf8]
719
    subs = []
720
    if arity.value > pobyso_max_arity:
721
        return(0,[])
722
    for i in xrange(arity.value):
723
        subs.append(int(subfunctions[i].value))
724
        #print subs[i]
725
    return(int(arity.value), subs)
726
    
727
def pobyso_get_prec():
728
    """ Legacy function. See pobyso_get_prec_so_sa(). """
729
    return(pobyso_get_prec_so_sa())
730

    
731
def pobyso_get_prec_so():
732
    """
733
    Get the current default precision in Sollya.
734
    The return value is a Sollya object.
735
    Usefull when modifying the precision back and forth by avoiding
736
    extra conversions.
737
    """
738
    return(sollya_lib_get_prec(None))
739
    
740
def pobyso_get_prec_so_sa():
741
    """
742
    Get the current default precision in Sollya.
743
    The return value is Sage/Python int.
744
    """
745
    precSo = sollya_lib_get_prec(None)
746
    precSa = c_int(0)
747
    sollya_lib_get_constant_as_int(byref(precSa), precSo)
748
    sollya_lib_clear_obj(precSo)
749
    return int(precSa.value)
750
# End pobyso_get_prec_so_sa.
751

    
752
def pobyso_get_prec_of_constant(ctExpSo):
753
    """ Legacy function. See pobyso_get_prec_of_constant_so_sa. """
754
    return(pobyso_get_prec_of_constant_so_sa(ctExpSo))
755

    
756
def pobyso_get_prec_of_constant_so_sa(ctExpSo):
757
    prec = c_int(0)
758
    retc = sollya_lib_get_prec_of_constant(byref(prec), ctExpSo, None)
759
    if retc == 0:
760
        return(None)
761
    return(int(prec.value))
762

    
763
def pobyso_get_prec_of_range_so_sa(rangeSo):
764
    prec = c_int(0)
765
    retc = sollya_lib_get_prec_of_range(byref(prec), rangeSo, None)
766
    if retc == 0:
767
        return(None)
768
    return(int(prec.value))
769
# End pobyso_get_prec_of_range_so_sa()
770

    
771
def pobyso_guess_degree_sa_sa(functionSa, intervalSa, approxErrorSa, 
772
                              weightSa=None, degreeBoundSa=None):
773
    """
774
    Sa_sa variant of the solly_guessdegree function.
775
    Return 0 if something goes wrong.
776
    """
777
    functionAsStringSa = functionSa._assume_str().replace('_SAGE_VAR_', '')
778
    functionSo = pobyso_parse_string_sa_so(functionAsStringSa)
779
    if pobyso_is_error_so_sa(functionSo):
780
        sollya_lib_clear_obj(functionSo)
781
        return 0
782
    rangeSo = pobyso_interval_to_range_sa_so(intervalSa)
783
    # The approximation error is expected to be a floating point number.
784
    if pobyso_is_floating_point_number_sa_sa(approxErrorSa):
785
        approxErrorSo = pobyso_constant_sa_so(approxErrorSa)
786
    else:
787
        approxErrorSo = pobyso_constant_sa_so(RR(approxErrorSa))
788
    if not weightSa is None:
789
        weightAsStringSa = weightSa._assume_str().replace('_SAGE_VAR_', '')
790
        weightSo = pobyso_parse_string_sa_so(weightAsStringSa)
791
        if pobyso_is_error_so_sa(weightSo):
792
            sollya_lib_clear_obj(functionSo)
793
            sollya_lib_clear_obj(rangeSo)
794
            sollya_lib_clear_obj(approxErrorSo)   
795
            sollya_lib_clear_obj(weightSo)
796
            return 0   
797
    else:
798
        weightSo = None
799
    if not degreeBoundSa is None:
800
        degreeBoundSo = pobyso_constant_from_int_sa_so(degreeBoundSa)
801
    else:
802
        degreeBoundSo = None
803
    guessedDegreeSa = pobyso_guess_degree_so_sa(functionSo,
804
                                                rangeSo,
805
                                                approxErrorSo,
806
                                                weightSo,
807
                                                degreeBoundSo)
808
    sollya_lib_clear_obj(functionSo)
809
    sollya_lib_clear_obj(rangeSo)
810
    sollya_lib_clear_obj(approxErrorSo)
811
    if not weightSo is None:
812
        sollya_lib_clear_obj(weightSo)
813
    if not degreeBoundSo is None:
814
        sollya_lib_clear_obj(degreeBoundSo)
815
    return guessedDegreeSa
816
# End poyso_guess_degree_sa_sa
817

    
818
def pobyso_guess_degree_so_sa(functionSo, rangeSo, errorSo, weightSo=None, \
819
                              degreeBoundSo=None):
820
    """
821
    Thin wrapper around the guessdegree function.
822
    Nevertheless, some precision control stuff has been appended.
823
    """
824
    # Deal with Sollya internal precision issues: if it is too small, 
825
    # compared with the error, increases it to about twice -log2(error).
826
    errorSa = pobyso_get_constant_as_rn_with_rf_so_sa(errorSo)
827
    log2ErrorSa = errorSa.log2()
828
    if log2ErrorSa < 0:
829
        neededPrecisionSa = int(2 * int(-log2ErrorSa) / 64) * 64
830
    else:
831
        neededPrecisionSa = int(2 * int(log2ErrorSa) / 64) * 64
832
    #print "Needed precision:", neededPrecisionSa
833
    currentPrecSa = pobyso_get_prec_so_sa()
834
    if neededPrecisionSa > currentPrecSa:
835
        currentPrecSo = pobyso_get_prec_so()
836
        pobyso_set_prec_sa_so(neededPrecisionSa)
837
    #print "Guessing degree..."
838
    # weightSo and degreeBoundsSo are optional arguments.
839
    # As declared, sollya_lib_guessdegree must take 5 arguments.
840
    if weightSo is None:
841
        degreeRangeSo = sollya_lib_guessdegree(functionSo, rangeSo, errorSo, 
842
                                               0, 0, None)
843
    elif degreeBoundSo is None:
844
        degreeRangeSo =  sollya_lib_guessdegree(functionSo, rangeSo, \
845
                                                errorSo, weightSo, 0, None)
846
    else:
847
        degreeRangeSo =  sollya_lib_guessdegree(functionSo, rangeSo, errorSo, \
848
                                                weightSo, degreeBoundSo, None)
849
    #print "...degree guess done."
850
    # Restore internal precision, if applicable.
851
    if neededPrecisionSa > currentPrecSa:
852
        pobyso_set_prec_so_so(currentPrecSo)
853
        sollya_lib_clear_obj(currentPrecSo)
854
    degreeIntervalSa = pobyso_range_to_interval_so_sa(degreeRangeSo)
855
    sollya_lib_clear_obj(degreeRangeSo)
856
    # When ok, both bounds match.
857
    # When the degree bound is too low, the upper bound is the degree
858
    # for which the error can be honored.
859
    # When it really goes wrong, the upper bound is infinity. 
860
    if degreeIntervalSa.lower() == degreeIntervalSa.upper():
861
        return int(degreeIntervalSa.lower())
862
    else:
863
        if degreeIntervalSa.upper().is_infinity():
864
            return None
865
        else:
866
            return int(degreeIntervalSa.upper())
867
    # End pobyso_guess_degree_so_sa
868

    
869
def pobyso_infnorm_so_so(func, interval, file = None, intervalList = None):
870
    print "Do not use this function. User pobyso_supnorm_so_so instead."
871
    return(None)
872

    
873
def pobyso_interval_to_range_sa_so(intervalSa, precisionSa=None):
874
    if precisionSa is None:
875
        precisionSa = intervalSa.parent().precision()
876
    intervalSo = pobyso_bounds_to_range_sa_so(intervalSa.lower(),\
877
                                              intervalSa.upper(),\
878
                                              precisionSa)
879
    return(intervalSo)
880
# End pobyso_interval_to_range_sa_so
881

    
882
def pobyso_is_error_so_sa(objSo):
883
    """
884
    Thin wrapper around the sollya_lib_obj_is_error() function.
885
    """
886
    if sollya_lib_obj_is_error(objSo) != 0:
887
        return True
888
    else:
889
        return False
890
# End pobyso_is_error-so_sa
891

    
892
def pobyso_is_floating_point_number_sa_sa(numberSa):
893
    """
894
    Check whether a Sage number is floating point
895
    """
896
    return numberSa.parent().__class__ is RR.__class__
897

    
898
def pobyso_lib_init():
899
    sollya_lib_init(None)
900

    
901
def pobyso_lib_close():
902
    sollya_lib_close(None)
903
    
904
def pobyso_name_free_variable(freeVariableNameSa):
905
    """ Legacy function. See pobyso_name_free_variable_sa_so. """
906
    pobyso_name_free_variable_sa_so(freeVariableNameSa)
907

    
908
def pobyso_name_free_variable_sa_so(freeVariableNameSa):
909
    """
910
    Set the free variable name in Sollya from a Sage string.
911
    """
912
    sollya_lib_name_free_variable(freeVariableNameSa)
913

    
914
def pobyso_parse_string(string):
915
    """ Legacy function. See pobyso_parse_string_sa_so. """
916
    return(pobyso_parse_string_sa_so(string))
917
 
918
def pobyso_parse_string_sa_so(string):
919
    """
920
    Get the Sollya expression computed from a Sage string or
921
    a Sollya error object if parsing failed.
922
    """
923
    return(sollya_lib_parse_string(string))
924

    
925
def pobyso_range(rnLowerBound, rnUpperBound):
926
    """ Legacy function. See pobyso_range_sa_so. """
927
    return(pobyso_range_sa_so(rnLowerBound, rnUpperBound)) 
928

    
929

    
930
def pobyso_range_to_interval_so_sa(rangeSo, realIntervalFieldSa = None):
931
    """
932
    Get a Sage interval from a Sollya range.
933
    If no realIntervalField is given as a parameter, the Sage interval
934
    precision is that of the Sollya range.
935
    Otherwise, the precision is that of the realIntervalField. In this case
936
    rounding may happen.
937
    """
938
    if realIntervalFieldSa is None:
939
        precSa = pobyso_get_prec_of_range_so_sa(rangeSo)
940
        realIntervalFieldSa = RealIntervalField(precSa)
941
    intervalSa = \
942
        pobyso_get_interval_from_range_so_sa(rangeSo, realIntervalFieldSa) 
943
    return(intervalSa)
944

    
945
def pobyso_remez_canonical_sa_sa(func, \
946
                                 degree, \
947
                                 lowerBound, \
948
                                 upperBound, \
949
                                 weight = None, \
950
                                 quality = None):
951
    """
952
    All arguments are Sage/Python.
953
    The functions (func and weight) must be passed as expressions or strings.
954
    Otherwise the function fails. 
955
    The return value is a Sage polynomial.
956
    """
957
    var('zorglub')    # Dummy variable name for type check only. Type of 
958
    # zorglub is "symbolic expression".
959
    polySo = pobyso_remez_canonical_sa_so(func, \
960
                                 degree, \
961
                                 lowerBound, \
962
                                 upperBound, \
963
                                 weight, \
964
                                 quality)
965
    # String test
966
    if parent(func) == parent("string"):
967
        functionSa = eval(func)
968
    # Expression test.
969
    elif type(func) == type(zorglub):
970
        functionSa = func
971
    else:
972
        return None
973
    #
974
    maxPrecision = 0
975
    if polySo is None:
976
        return(None)
977
    maxPrecision = pobyso_get_max_prec_of_exp_so_sa(polySo)
978
    RRRRSa = RealField(maxPrecision)
979
    polynomialRingSa = RRRRSa[functionSa.variables()[0]]
980
    expSa = pobyso_get_sage_exp_from_sollya_exp_so_sa(polySo, RRRRSa)
981
    polySa = polynomial(expSa, polynomialRingSa)
982
    sollya_lib_clear_obj(polySo)
983
    return(polySa)
984
# End pobyso_remez_canonical_sa_sa
985
    
986
def pobyso_remez_canonical(func, \
987
                           degree, \
988
                           lowerBound, \
989
                           upperBound, \
990
                           weight = "1", \
991
                           quality = None):
992
    """ Legacy function. See pobyso_remez_canonical_sa_so. """
993
    return(pobyso_remez_canonical_sa_so(func, \
994
                                        degree, \
995
                                        lowerBound, \
996
                                        upperBound, \
997
                                        weight, \
998
                                        quality))
999
def pobyso_remez_canonical_sa_so(func, \
1000
                                 degree, \
1001
                                 lowerBound, \
1002
                                 upperBound, \
1003
                                 weight = None, \
1004
                                 quality = None):
1005
    """
1006
    All arguments are Sage/Python.
1007
    The functions (func and weight) must be passed as expressions or strings.
1008
    Otherwise the function fails. 
1009
    The return value is a pointer to a Sollya function.
1010
    """
1011
    var('zorglub')    # Dummy variable name for type check only. Type of
1012
    # zorglub is "symbolic expression".
1013
    currentVariableNameSa = None
1014
    # The func argument can be of different types (string, 
1015
    # symbolic expression...)
1016
    if parent(func) == parent("string"):
1017
        localFuncSa = eval(func)
1018
        if len(localFuncSa.variables()) > 0:
1019
            currentVariableNameSa = localFuncSa.variables()[0]
1020
            sollya_lib_name_free_variable(str(currentVariableNameSa))
1021
            functionSo = \
1022
              sollya_lib_parse_string(localFuncSa._assume_str().replace('_SAGE_VAR_', ''))
1023
    # Expression test.
1024
    elif type(func) == type(zorglub):
1025
        # Until we are able to translate Sage expressions into Sollya 
1026
        # expressions : parse the string version.
1027
        if len(func.variables()) > 0:
1028
            currentVariableNameSa = func.variables()[0]
1029
            sollya_lib_name_free_variable(str(currentVariableNameSa))
1030
            functionSo = \
1031
              sollya_lib_parse_string(func._assume_str().replace('_SAGE_VAR_', ''))
1032
    else:
1033
        return(None)
1034
    if weight is None: # No weight given -> 1.
1035
        weightSo = pobyso_constant_1_sa_so()
1036
    elif parent(weight) == parent("string"): # Weight given as string: parse it.
1037
        weightSo = sollya_lib_parse_string(func)
1038
    elif type(weight) == type(zorglub): # Weight given as symbolice expression.
1039
        functionSo = \
1040
          sollya_lib_parse_string_sa_so(weight._assume_str().replace('_SAGE_VAR_', ''))
1041
    else:
1042
        return(None)
1043
    degreeSo = pobyso_constant_from_int(degree)
1044
    rangeSo = pobyso_bounds_to_range_sa_so(lowerBound, upperBound)
1045
    if not quality is None:
1046
        qualitySo= pobyso_constant_sa_so(quality)
1047
    else:
1048
        qualitySo = None
1049
        
1050
    remezPolySo = sollya_lib_remez(functionSo, \
1051
                                   degreeSo, \
1052
                                   rangeSo, \
1053
                                   weightSo, \
1054
                                   qualitySo, \
1055
                                   None)
1056
    sollya_lib_clear_obj(functionSo)
1057
    sollya_lib_clear_obj(degreeSo)
1058
    sollya_lib_clear_obj(rangeSo)
1059
    sollya_lib_clear_obj(weightSo)
1060
    if not qualitySo is None:
1061
        sollya_lib_clear_obj(qualitySo)
1062
    return(remezPolySo)
1063
# End pobyso_remez_canonical_sa_so
1064

    
1065
def pobyso_remez_canonical_so_so(funcSo, \
1066
                                 degreeSo, \
1067
                                 rangeSo, \
1068
                                 weightSo = pobyso_constant_1_sa_so(),\
1069
                                 qualitySo = None):
1070
    """
1071
    All arguments are pointers to Sollya objects.
1072
    The return value is a pointer to a Sollya function.
1073
    """
1074
    if not sollya_lib_obj_is_function(funcSo):
1075
        return(None)
1076
    return(sollya_lib_remez(funcSo, degreeSo, rangeSo, weightSo, qualitySo, None))
1077
    
1078
def pobyso_set_canonical_off():
1079
    sollya_lib_set_canonical(sollya_lib_off())
1080

    
1081
def pobyso_set_canonical_on():
1082
    sollya_lib_set_canonical(sollya_lib_on())
1083

    
1084
def pobyso_set_prec(p):
1085
    """ Legacy function. See pobyso_set_prec_sa_so. """
1086
    pobyso_set_prec_sa_so(p)
1087

    
1088
def pobyso_set_prec_sa_so(p):
1089
    a = c_int(p)
1090
    precSo = c_void_p(sollya_lib_constant_from_int(a))
1091
    sollya_lib_set_prec(precSo, None)
1092

    
1093
def pobyso_set_prec_so_so(newPrecSo):
1094
    sollya_lib_set_prec(newPrecSo, None)
1095

    
1096
def pobyso_supnorm_so_so(polySo, funcSo, intervalSo, errorTypeSo = None,\
1097
                         accuracySo = None):
1098
    """
1099
    Computes the supnorm of the approximation error between the given 
1100
    polynomial and function.
1101
    errorTypeSo defaults to "absolute".
1102
    accuracySo defaults to 2^(-40).
1103
    """
1104
    if errorTypeSo is None:
1105
        errorTypeSo = sollya_lib_absolute(None)
1106
        errorTypeIsNone = True
1107
    else:
1108
        errorTypeIsNone = False
1109
    #
1110
    if accuracySo is None:
1111
        # Notice the **!
1112
        accuracySo = pobyso_constant_sa_so(RR(2**(-40)))
1113
        accuracyIsNone = True
1114
    else:
1115
        accuracyIsNone = False
1116
    pobyso_autoprint(accuracySo)
1117
    resultSo = \
1118
        sollya_lib_supnorm(polySo, funcSo, intervalSo, errorTypeSo, \
1119
                              accuracySo)
1120
    if errorTypeIsNone:
1121
        sollya_lib_clear_obj(errorTypeSo)
1122
    if accuracyIsNone:
1123
        sollya_lib_clear_obj(accuracySo)
1124
    return resultSo
1125
# End pobyso_supnorm_so_so
1126

    
1127
def pobyso_taylor_expansion_no_change_var_so_so(functionSo, 
1128
                                                degreeSo, 
1129
                                                rangeSo,
1130
                                                errorTypeSo=None, 
1131
                                                sollyaPrecSo=None):
1132
    """
1133
    Compute the Taylor expansion without the variable change
1134
    x -> x-intervalCenter.
1135
    """
1136
    # No global change of the working precision.
1137
    if not sollyaPrecSo is None:
1138
        initialPrecSo = sollya_lib_get_prec(None)
1139
        sollya_lib_set_prec(sollyaPrecSo)
1140
    # Error type stuff: default to absolute.
1141
    if errorTypeSo is None:
1142
        errorTypeIsNone = True
1143
        errorTypeSo = sollya_lib_absolute(None)
1144
    else:
1145
        errorTypeIsNone = False
1146
    intervalCenterSo = sollya_lib_mid(rangeSo, None)
1147
    taylorFormSo = sollya_lib_taylorform(functionSo, degreeSo,
1148
                                         intervalCenterSo,
1149
                                         rangeSo, errorTypeSo, None)
1150
    # taylorFormListSaSo is a Python list of Sollya objects references that 
1151
    # are copies of the elements of taylorFormSo.
1152
    # pobyso_get_list_elements_so_so clears taylorFormSo.
1153
    (taylorFormListSaSo, numElementsSa, isEndEllipticSa) = \
1154
        pobyso_get_list_elements_so_so(taylorFormSo)
1155
    polySo = sollya_lib_copy_obj(taylorFormListSaSo[0])
1156
    #print "Num elements:", numElementsSa
1157
    sollya_lib_clear_obj(taylorFormSo)
1158
    #polySo = taylorFormListSaSo[0]
1159
    #errorRangeSo = sollya_lib_copy_obj(taylorFormListSaSo[2])
1160
    errorRangeSo = taylorFormListSaSo[2]
1161
    # No copy_obj needed here: a new object is created.
1162
    maxErrorSo = sollya_lib_sup(errorRangeSo)
1163
    # If changed, reset the Sollya working precision.
1164
    if not sollyaPrecSo is None:
1165
        sollya_lib_set_prec(initialPrecSo)
1166
        sollya_lib_clear_obj(initialPrecSo)
1167
    if errorTypeIsNone:
1168
        sollya_lib_clear_obj(errorTypeSo)
1169
    pobyso_clear_taylorform_sa_so(taylorFormListSaSo)
1170
    return((polySo, intervalCenterSo, maxErrorSo))
1171
# end pobyso_taylor_expansion_no_change_var_so_so
1172

    
1173
def pobyso_taylor_expansion_with_change_var_so_so(functionSo, degreeSo, \
1174
                                                  rangeSo, \
1175
                                                  errorTypeSo=None, \
1176
                                                  sollyaPrecSo=None):
1177
    """
1178
    Compute the Taylor expansion with the variable change
1179
    x -> (x-intervalCenter) included.
1180
    """
1181
    # No global change of the working precision.
1182
    if not sollyaPrecSo is None:
1183
        initialPrecSo = sollya_lib_get_prec(None)
1184
        sollya_lib_set_prec(sollyaPrecSo)
1185
    #
1186
    # Error type stuff: default to absolute.
1187
    if errorTypeSo is None:
1188
        errorTypeIsNone = True
1189
        errorTypeSo = sollya_lib_absolute(None)
1190
    else:
1191
        errorTypeIsNone = False
1192
    intervalCenterSo = sollya_lib_mid(rangeSo)
1193
    taylorFormSo = sollya_lib_taylorform(functionSo, degreeSo, \
1194
                                         intervalCenterSo, \
1195
                                         rangeSo, errorTypeSo, None)
1196
    # taylorFormListSaSo is a Python list of Sollya objects references that 
1197
    # are copies of the elements of taylorFormSo.
1198
    # pobyso_get_list_elements_so_so clears taylorFormSo.
1199
    (taylorFormListSo, numElements, isEndElliptic) = \
1200
        pobyso_get_list_elements_so_so(taylorFormSo)
1201
    polySo = taylorFormListSo[0]
1202
    errorRangeSo = taylorFormListSo[2]
1203
    maxErrorSo = sollya_lib_sup(errorRangeSo)
1204
    changeVarExpSo = sollya_lib_build_function_sub(\
1205
                       sollya_lib_build_function_free_variable(),\
1206
                       sollya_lib_copy_obj(intervalCenterSo))
1207
    polyVarChangedSo = sollya_lib_evaluate(polySo, changeVarExpSo) 
1208
    sollya_lib_clear_obj(changeVarExpSo)
1209
    # If changed, reset the Sollya working precision.
1210
    if not sollyaPrecSo is None:
1211
        sollya_lib_set_prec(initialPrecSo)
1212
        sollya_lib_clear_obj(initialPrecSo)
1213
    if errorTypeIsNone:
1214
        sollya_lib_clear_obj(errorTypeSo)
1215
    sollya_lib_clear_obj(taylorFormSo)
1216
    # Do not clear maxErrorSo.
1217
    return((polyVarChangedSo, intervalCenterSo, maxErrorSo))
1218
# end pobyso_taylor_expansion_with_change_var_so_so
1219

    
1220
def pobyso_taylor(function, degree, point):
1221
    """ Legacy function. See pobysoTaylor_so_so. """
1222
    return(pobyso_taylor_so_so(function, degree, point))
1223

    
1224
def pobyso_taylor_so_so(functionSo, degreeSo, pointSo):
1225
    return(sollya_lib_taylor(functionSo, degreeSo, pointSo))
1226
    
1227
def pobyso_taylorform(function, degree, point = None, 
1228
                      interval = None, errorType=None):
1229
    """ Legacy function. See pobyso_taylorform_sa_sa;"""
1230
    
1231
def pobyso_taylorform_sa_sa(functionSa, \
1232
                            degreeSa, \
1233
                            pointSa, \
1234
                            intervalSa=None, \
1235
                            errorTypeSa=None, \
1236
                            precisionSa=None):
1237
    """
1238
    Compute the Taylor form of 'degreeSa' for 'functionSa' at 'pointSa' 
1239
    for 'intervalSa' with 'errorTypeSa' (a string) using 'precisionSa'. 
1240
    point: must be a Real or a Real interval.
1241
    return the Taylor form as an array
1242
    TODO: take care of the interval and of the point when it is an interval;
1243
          when errorType is not None;
1244
          take care of the other elements of the Taylor form (coefficients 
1245
          errors and delta.
1246
    """
1247
    # Absolute as the default error.
1248
    if errorTypeSa is None:
1249
        errorTypeSo = sollya_lib_absolute()
1250
    elif errorTypeSa == "relative":
1251
        errorTypeSo = sollya_lib_relative()
1252
    elif errortypeSa == "absolute":
1253
        errorTypeSo = sollya_lib_absolute()
1254
    else:
1255
        # No clean up needed.
1256
        return None
1257
    # Global precision stuff
1258
    precisionChangedSa = False
1259
    currentSollyaPrecSo = pobyso_get_prec_so()
1260
    currentSollyaPrecSa = pobyso_constant_from_int_so_sa(currentSollyaPrecSo)
1261
    if not precisionSa is None:
1262
        if precisionSa > currentSollyaPrecSa:
1263
            pobyso_set_prec_sa_so(precisionSa)
1264
            precisionChangedSa = True
1265
            
1266
    if len(functionSa.variables()) > 0:
1267
        varSa = functionSa.variables()[0]
1268
        pobyso_name_free_variable_sa_so(str(varSa))
1269
    # In any case (point or interval) the parent of pointSa has a precision
1270
    # method.
1271
    pointPrecSa = pointSa.parent().precision()
1272
    if precisionSa > pointPrecSa:
1273
        pointPrecSa = precisionSa
1274
    # In any case (point or interval) pointSa has a base_ring() method.
1275
    pointBaseRingString = str(pointSa.base_ring())
1276
    if re.search('Interval', pointBaseRingString) is None: # Point
1277
        pointSo = pobyso_constant_sa_so(pointSa, pointPrecSa)
1278
    else: # Interval.
1279
        pointSo = pobyso_interval_to_range_sa_so(pointSa, pointPrecSa)
1280
    # Sollyafy the function.
1281
    functionSo = pobyso_parse_string_sa_so(functionSa._assume_str().replace('_SAGE_VAR_', ''))
1282
    if sollya_lib_obj_is_error(functionSo):
1283
        print "pobyso_tailorform: function string can't be parsed!"
1284
        return None
1285
    # Sollyafy the degree
1286
    degreeSo = sollya_lib_constant_from_int(int(degreeSa))
1287
    # Sollyafy the point
1288
    # Call Sollya
1289
    taylorFormSo = \
1290
        sollya_lib_taylorform(functionSo, degreeSo, pointSo, errorTypeSo,\
1291
                                         None)
1292
    sollya_lib_clear_obj(functionSo)
1293
    sollya_lib_clear_obj(degreeSo)
1294
    sollya_lib_clear_obj(pointSo)
1295
    sollya_lib_clear_obj(errorTypeSo)
1296
    (tfsAsList, numElements, isEndElliptic) = \
1297
            pobyso_get_list_elements_so_so(taylorFormSo)
1298
    polySo = tfsAsList[0]
1299
    maxPrecision = pobyso_get_max_prec_of_exp_so_sa(polySo)
1300
    polyRealField = RealField(maxPrecision)
1301
    expSa = pobyso_get_sage_exp_from_sollya_exp_so_sa(polySo, polyRealField)
1302
    if precisionChangedSa:
1303
        sollya_lib_set_prec(currentSollyaPrecSo)
1304
        sollya_lib_clear_obj(currentSollyaPrecSo)
1305
    polynomialRing = polyRealField[str(varSa)]
1306
    polySa = polynomial(expSa, polynomialRing)
1307
    taylorFormSa = [polySa]
1308
    # Final clean-up.
1309
    sollya_lib_clear_obj(taylorFormSo)
1310
    return(taylorFormSa)
1311
# End pobyso_taylor_form_sa_sa
1312

    
1313
def pobyso_taylorform_so_so(functionSo, degreeSo, pointSo, intervalSo=None, \
1314
                            errorTypeSo=None):
1315
    createdErrorType = False
1316
    if errorTypeSo is None:
1317
        errorTypeSo = sollya_lib_absolute()
1318
        createdErrorType = True
1319
    else:
1320
        #TODO: deal with the other case.
1321
        pass
1322
    if intervalSo is None:
1323
        resultSo = sollya_lib_taylorform(functionSo, degreeSo, pointSo, \
1324
                                         errorTypeSo, None)
1325
    else:
1326
        resultSo = sollya_lib_taylorform(functionSo, degreeSo, pointSo, \
1327
                                         intervalSo, errorTypeSo, None)
1328
    if createdErrorType:
1329
        sollya_lib_clear_obj(errorTypeSo)
1330
    return(resultSo)
1331
        
1332

    
1333
def pobyso_univar_polynomial_print_reverse(polySa):
1334
    """ Legacy function. See pobyso_univar_polynomial_print_reverse_sa_sa. """
1335
    return(pobyso_univar_polynomial_print_reverse_sa_sa(polySa))
1336

    
1337
def pobyso_univar_polynomial_print_reverse_sa_sa(polySa):
1338
    """
1339
    Return the string representation of a univariate polynomial with
1340
    monomials ordered in the x^0..x^n order of the monomials.
1341
    Remember: Sage
1342
    """
1343
    polynomialRing = polySa.base_ring()
1344
    # A very expensive solution:
1345
    # -create a fake multivariate polynomial field with only one variable,
1346
    #   specifying a negative lexicographical order;
1347
    mpolynomialRing = PolynomialRing(polynomialRing.base(), \
1348
                                     polynomialRing.variable_name(), \
1349
                                     1, order='neglex')
1350
    # - convert the univariate argument polynomial into a multivariate
1351
    #   version;
1352
    p = mpolynomialRing(polySa)
1353
    # - return the string representation of the converted form.
1354
    # There is no simple str() method defined for p's class.
1355
    return(p.__str__())
1356
#
1357
print pobyso_get_prec()  
1358
pobyso_set_prec(165)
1359
print pobyso_get_prec()  
1360
a=100
1361
print type(a)
1362
id(a)
1363
print "Max arity: ", pobyso_max_arity
1364
print "Function tripleDouble (43) as a string: ", pobyso_function_type_as_string(43)
1365
print "Function None (44) as a string: ", pobyso_function_type_as_string(44)
1366
print "...Pobyso check done"