Statistiques
| Révision :

root / pobysoPythonSage / src / pobyso.py @ 217

Historique | Voir | Annoter | Télécharger (66,68 ko)

1
"""
2
@file pobyso.py
3
Actual functions to use in Sage
4
ST 2012-11-13
5

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

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

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

    
87
pobyso_max_arity = 9
88

    
89
def pobyso_absolute_so_so():
90
    return(sollya_lib_absolute(None))
91

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

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

    
133
def pobyso_build_end_elliptic_list_so_so(*args):
134
    """
135
    From argumrny Sollya objects, create a Sollya end elliptic list.
136
    Elements of the list are "eaten" (should not be cleared individualy, 
137
    are cleared when the list is cleared).
138
    """
139
    if len(args) == 0:
140
        ## Called with an empty list produced "error".
141
        return sollya_lib_build_end_elliptic_list(None)
142
    index = 0
143
    ## One can not append elements to an elliptic list, prepend only is 
144
    #  permitted.
145
    for argument in reversed(args):
146
        if index == 0:
147
            listSo = sollya_lib_build_end_elliptic_list(argument, None)
148
        else:
149
            listSo = sollya_lib_prepend(argument, listSo)
150
        index += 1
151
    return listSo
152
        
153
# End pobyso_build_end_elliptic_list_so_so
154

    
155
def pobyso_build_function_sub_so_so(exp1So, exp2So):
156
    return(sollya_lib_build_function_sub(exp1So, exp2So))
157

    
158
def pobyso_change_var_in_function_so_so(funcSo, chvarExpSo):
159
    """
160
    Variable change in a function.
161
    """
162
    return(sollya_lib_evaluate(funcSo,chvarExpSo))
163
# End pobyso_change_var_in_function_so_so     
164

    
165
def pobyso_chebyshevform_so_so(functionSo, degreeSo, intervalSo):
166
    resultSo = sollya_lib_chebyshevform(functionSo, degreeSo, intervalSo)
167
    return(resultSo)
168
# End pobyso_chebyshevform_so_so.
169

    
170
def pobyso_clear_taylorform_sa_so(taylorFormSaSo):
171
    """
172
    This method is necessary to correctly clean up the memory from Taylor forms.
173
    These are made of a Sollya object, a Sollya object list, a Sollya object.
174
    For no clearly understood reason, sollya_lib_clear_object_list crashed 
175
    when applied to the object list.
176
    Here, we decompose it into Sage list of Sollya objects references and we
177
     clear them one by one. 
178
    """
179
    sollya_lib_clear_obj(taylorFormSaSo[0])
180
    (coefficientsErrorsListSaSo, numElementsSa, isEndEllipticSa) = \
181
        pobyso_get_list_elements_so_so(taylorFormSaSo[1])
182
    for element in coefficientsErrorsListSaSo:
183
        sollya_lib_clear_obj(element)
184
    sollya_lib_clear_obj(taylorFormSaSo[1])
185
    sollya_lib_clear_obj(taylorFormSaSo[2])
186
# End pobyso_clear_taylorform_sa_so 
187

    
188
def pobyso_cmp(rnArgSa, cteSo):
189
    """
190
    Compare the MPFR value a RealNumber with that of a Sollya constant.
191
    
192
    Get the value of the Sollya constant into a RealNumber and compare
193
    using MPFR. Could be optimized by working directly with a mpfr_t
194
    for the intermediate number. 
195
    """
196
    # Get the precision of the Sollya constant to build a Sage RealNumber 
197
    # with enough precision.to hold it.
198
    precisionOfCte = c_int(0)
199
    # From the Sollya constant, create a local Sage RealNumber.
200
    sollya_lib_get_prec_of_constant(precisionOfCte, cteSo) 
201
    #print "Precision of constant: ", precisionOfCte
202
    RRRR = RealField(precisionOfCte.value)
203
    rnLocalSa = RRRR(0)
204
    sollya_lib_get_constant(get_rn_value(rnLocalSa), cteSo)
205
    #
206
    ## Compare the Sage RealNumber version of the Sollya constant with rnArg.
207
    return(cmp_rn_value(rnArgSa, rnLocal))
208
# End pobyso_smp
209

    
210
def pobyso_compute_pos_function_abs_val_bounds_sa_sa(funcSa, lowerBoundSa, \
211
                                                     upperBoundSa):
212
    """
213
    TODO: completely rework and test.
214
    """
215
    pobyso = pobyso_name_free_variable_sa_so(funcSa.variables()[0])
216
    funcSo = pobyso_parse_string(funcSa._assume_str().replace('_SAGE_VAR_', ''))
217
    rangeSo = pobyso_range_sa_so(lowerBoundSa, upperBoundSa)
218
    infnormSo = pobyso_infnorm_so_so(funcSo,rangeSo)
219
    # Sollya return the infnorm as an interval.
220
    fMaxSa = pobyso_get_interval_from_range_so_sa(infnormSo)
221
    # Get the top bound and compute the binade top limit.
222
    fMaxUpperBoundSa = fMaxSa.upper()
223
    binadeTopLimitSa = 2**ceil(fMaxUpperBoundSa.log2())
224
    # Put up together the function to use to compute the lower bound.
225
    funcAuxSo = pobyso_parse_string(str(binadeTopLimitSa) +  \
226
                                    '-(' + f._assume_str().replace('_SAGE_VAR_', '') + ')')
227
    pobyso_autoprint(funcAuxSo)
228
    # Clear the Sollya range before a new call to infnorm and issue the call.
229
    sollya_lib_clear_obj(infnormSo)
230
    infnormSo = pobyso_infnorm_so_so(funcAuxSo,rangeSo)
231
    fMinSa = pobyso_get_interval_from_range_so_sa(infnormSo)
232
    sollya_lib_clear_obj(infnormSo)
233
    fMinLowerBoundSa = binadeTopLimitSa - fMinSa.lower()
234
    # Compute the maximum of the precisions of the different bounds.
235
    maxPrecSa = max([fMinLowerBoundSa.parent().precision(), \
236
                     fMaxUpperBoundSa.parent().precision()])
237
    # Create a RealIntervalField and create an interval with the "good" bounds.
238
    RRRI = RealIntervalField(maxPrecSa)
239
    imageIntervalSa = RRRI(fMinLowerBoundSa, fMaxUpperBoundSa)
240
    # Free the unneeded Sollya objects
241
    sollya_lib_clear_obj(funcSo)
242
    sollya_lib_clear_obj(funcAuxSo)
243
    sollya_lib_clear_obj(rangeSo)
244
    return(imageIntervalSa)
245
# End pobyso_compute_pos_function_abs_val_bounds_sa_sa
246

    
247
def pobyso_compute_precision_decay_ratio_function_sa_so():
248
    """
249
    Compute the precision decay ratio function for polynomial 
250
    coefficient progressive trucation.
251
    """
252
    functionText = """
253
    proc(deg, a, b, we, wq) 
254
    {
255
      k = we * (exp(x/a)-1) + wq * (b*x)^2 + (1-we-wq) * x;
256
      return k/k(d);
257
    };
258
    """
259
    return pobyso_parse_string_sa_so(functionText)
260
# End  pobyso_compute_precision_decay_ratio_function.
261

    
262

    
263
def pobyso_constant(rnArg):
264
    """ Legacy function. See pobyso_constant_sa_so. """
265
    return(pobyso_constant_sa_so(rnArg))
266
    
267
def pobyso_constant_sa_so(rnArgSa, precisionSa=None):
268
    """
269
    Create a Sollya constant from a Sage RealNumber.
270
    The sollya_lib_constant() function creates a constant
271
    with the same precision as the source.
272
    """
273
    ## Precision stuff. If one wants to change precisions,
274
    #  everything takes place in Sage. That only makes
275
    #  sense if one wants to reduce the precision.
276
    if not precisionSa is None:
277
        RRR = RealField(precisionSa)
278
        rnArgSa = RRR(rnArgSa)
279
    #print rnArgSa, rnArgSa.precision()
280
    # Sollya constant creation takes place here.
281
    return sollya_lib_constant(get_rn_value(rnArgSa))
282
# End pobyso_constant_sa_so
283
     
284
def pobyso_constant_0_sa_so():
285
    """
286
    Obvious.
287
    """
288
    return pobyso_constant_from_int_sa_so(0)
289

    
290
def pobyso_constant_1():
291
    """
292
    Obvious.
293
    Legacy function. See pobyso_constant_so_so. 
294
    """
295
    return pobyso_constant_1_sa_so()
296

    
297
def pobyso_constant_1_sa_so():
298
    """
299
    Obvious.
300
    """
301
    return(pobyso_constant_from_int_sa_so(1))
302

    
303
def pobyso_constant_from_int(anInt):
304
    """ Legacy function. See pobyso_constant_from_int_sa_so. """
305
    return pobyso_constant_from_int_sa_so(anInt)
306

    
307
def pobyso_constant_from_int_sa_so(anInt):
308
    """
309
    Get a Sollya constant from a Sage int.
310
    """
311
    return sollya_lib_constant_from_int64(long(anInt))
312

    
313
def pobyso_constant_from_int_so_sa(constSo):
314
    """
315
    Get a Sage int from a Sollya int constant.
316
    Usefull for precision or powers in polynomials.
317
    """
318
    constSa = c_long(0)
319
    sollya_lib_get_constant_as_int64(byref(constSa), constSo)
320
    return constSa.value
321
# End pobyso_constant_from_int_so_sa
322

    
323
def pobyso_constant_from_mpq_sa_so(rationalSa):
324
    """
325
    Make a Sollya constant from Sage rational.
326
    The Sollya constant is an unevaluated expression.
327
    Hence no precision argument is needed.
328
    It is better to leave this way since Sollya has its own
329
    optimized evaluation mecanism that tries very hard to
330
    return exact values or at least faithful ones.
331
    """
332
    ratExprSo = \
333
        sollya_lib_constant_from_mpq(sgmp_get_rational_value(rationalSa))
334
    return ratExprSo
335
# End pobyso_constant_from_mpq_sa_so.
336

    
337
def pobyso_constant_sollya_prec_sa_so(rnArgSa):
338
    """
339
    Create a Sollya constant from a Sage RealNumber at the
340
    current precision in Sollya.
341
    """
342
    currentSollyaPrecSa = pobyso_get_prec_so_sa()
343
    return pobyso_constant_sa_so(rnArgSa, currentSollyaPrecSa)
344
# End pobyso_constant_sollya_prec_sa_so
345

    
346
def pobyso_end_elliptic_list_so_sa_so(objectsListSo, intCountSa):
347
    """
348
    Create a Sollya end elliptic list made of the objectListSo[0] to
349
     objectsListSo[intCountSa-1] objects.
350
    """     
351
    return sollya_lib_end_elliptic_list(objectSo, int(intCountSa))
352

    
353
def pobyso_error_so():
354
    return sollya_lib_error(None)
355
# End pobyso_error().
356

    
357
def pobyso_evaluate_so_so(funcSo, argumentSo):
358
    """
359
    Evaluates funcSo for arguemntSo through sollya_lib_evaluate().
360
    """
361
    return sollya_lib_evaluate(funcSo, argumentSo)
362
# End pobyso_evaluate_so_so.
363

    
364
def pobyso_float_poly_sa_so(polySa, precSa = None):
365
    """
366
    Create a Sollya polynomial from a Sage RealField polynomial.
367
    """
368
    ## TODO: filter arguments.
369
    ## Precision. If a precision is given, convert the polynomial
370
    #  into the right polynomial field. If not convert it straight
371
    #  to Sollya.
372
    if not precSa is None:
373
        RRR = RealField(precSa)
374
        ## Create a Sage polynomial in the "right" precision.
375
        P_RRR = RRR[polySa.variables()[0]]
376
        polyFloatSa = P_RRR(polySa)
377
    else:
378
        polyFloatSa = polySa
379
        precSa = polySa.parent().base_ring().precision()
380
    ## Get exponents and coefficients.
381
    exponentsSa = polyFloatSa.exponents()
382
    coefficientsSa = polyFloatSa.coefficients()
383
    ## Build the polynomial.
384
    polySo = None
385
    for coefficientSa, exponentSa in zip(coefficientsSa, exponentsSa):
386
        #print coefficientSa.n(prec=precSa), exponentSa
387
        coefficientSo = \
388
            pobyso_constant_sa_so(coefficientSa)
389
        #pobyso_autoprint(coefficientSo)
390
        exponentSo = \
391
            pobyso_constant_from_int_sa_so(exponentSa)
392
        #pobyso_autoprint(exponentSo)
393
        monomialSo = sollya_lib_build_function_pow(
394
                       sollya_lib_build_function_free_variable(),
395
                       exponentSo)
396
        if polySo is None:
397
            polySo = sollya_lib_build_function_mul(coefficientSo,
398
                                                   monomialSo)
399
        else:
400
            polyTermSo = sollya_lib_build_function_mul(coefficientSo,
401
                                                       monomialSo)
402
            polySo = sollya_lib_build_function_add(polySo, polyTermSo)
403
    return polySo
404
# End pobyso_float_poly_sa_so    
405

    
406
def pobyso_float_poly_so_sa(polySo, realFieldSa=None):
407
    """
408
    Convert a Sollya polynomial into a Sage floating-point polynomial.
409
    We assume that the polynomial is in canonical form.
410
    If no realField is given, a RealField corresponding to the maximum 
411
    precision of the coefficients is internally computed.
412
    The real field is not returned but can be easily retrieved from 
413
    the polynomial itself.
414
    ALGORITHM:
415
    - (optional) compute the RealField of the coefficients;
416
    - convert the Sollya expression into a Sage expression;
417
    - convert the Sage expression into a Sage polynomial
418
    TODO: the canonical thing for the polynomial.
419
    """    
420
    if realFieldSa is None:
421
        expressionPrecSa = pobyso_get_max_prec_of_exp_so_sa(polySo)
422
        print "Maximum precision of Sollya polynomial coefficients:", expressionPrecSa
423
        realFieldSa      = RealField(expressionPrecSa)
424
    #print "Sollya expression before...",
425
    #pobyso_autoprint(polySo)
426

    
427
    expressionSa = pobyso_get_sage_exp_from_sollya_exp_so_sa(polySo,
428
                                                             realFieldSa)
429
    #print "...Sollya expression after.",
430
    #pobyso_autoprint(polySo)
431
    polyVariableSa = expressionSa.variables()[0]
432
    polyRingSa     = realFieldSa[str(polyVariableSa)]
433
    #print polyRingSa
434
    # Do not use the polynomial(expressionSa, ring=polyRingSa) form!
435
    polynomialSa = polyRingSa(expressionSa)
436
    polyCoeffsListSa = polynomialSa.coefficients()
437
    #for coeff in polyCoeffsListSa:
438
    #    print coeff.abs().n()
439
    return polynomialSa
440
# End pobyso_float_poly_so_sa
441

    
442
def pobyso_free_variable():
443
    """
444
    Ultra thin wrapper around the sollya_lib_function_build_free_variable function.
445
    """
446
    return sollya_lib_build_function_free_variable()
447
    
448
def pobyso_function_type_as_string(funcType):
449
    """ Legacy function. See pobyso_function_type_as_string_so_sa. """
450
    return(pobyso_function_type_as_string_so_sa(funcType))
451

    
452
def pobyso_function_type_as_string_so_sa(funcType):
453
    """
454
    Numeric Sollya function codes -> Sage mathematical function names.
455
    Notice that pow -> ^ (a la Sage, not a la Python).
456
    """
457
    if funcType == SOLLYA_BASE_FUNC_ABS:
458
        return "abs"
459
    elif funcType == SOLLYA_BASE_FUNC_ACOS:
460
        return "arccos"
461
    elif funcType == SOLLYA_BASE_FUNC_ACOSH:
462
        return "arccosh"
463
    elif funcType == SOLLYA_BASE_FUNC_ADD:
464
        return "+"
465
    elif funcType == SOLLYA_BASE_FUNC_ASIN:
466
        return "arcsin"
467
    elif funcType == SOLLYA_BASE_FUNC_ASINH:
468
        return "arcsinh"
469
    elif funcType == SOLLYA_BASE_FUNC_ATAN:
470
        return "arctan"
471
    elif funcType == SOLLYA_BASE_FUNC_ATANH:
472
        return "arctanh"
473
    elif funcType == SOLLYA_BASE_FUNC_CEIL:
474
        return "ceil"
475
    elif funcType == SOLLYA_BASE_FUNC_CONSTANT:
476
        return "cte"
477
    elif funcType == SOLLYA_BASE_FUNC_COS:
478
        return "cos"
479
    elif funcType == SOLLYA_BASE_FUNC_COSH:
480
        return "cosh"
481
    elif funcType == SOLLYA_BASE_FUNC_DIV:
482
        return "/"
483
    elif funcType == SOLLYA_BASE_FUNC_DOUBLE:
484
        return "double"
485
    elif funcType == SOLLYA_BASE_FUNC_DOUBLEDOUBLE:
486
        return "doubleDouble"
487
    elif funcType == SOLLYA_BASE_FUNC_DOUBLEEXTENDED:
488
        return "doubleDxtended"
489
    elif funcType == SOLLYA_BASE_FUNC_ERF:
490
        return "erf"
491
    elif funcType == SOLLYA_BASE_FUNC_ERFC:
492
        return "erfc"
493
    elif funcType == SOLLYA_BASE_FUNC_EXP:
494
        return "exp"
495
    elif funcType == SOLLYA_BASE_FUNC_EXP_M1:
496
        return "expm1"
497
    elif funcType == SOLLYA_BASE_FUNC_FLOOR:
498
        return "floor"
499
    elif funcType == SOLLYA_BASE_FUNC_FREE_VARIABLE:
500
        return "freeVariable"
501
    elif funcType == SOLLYA_BASE_FUNC_HALFPRECISION:
502
        return "halfPrecision"
503
    elif funcType == SOLLYA_BASE_FUNC_LIBRARYCONSTANT:
504
        return "libraryConstant"
505
    elif funcType == SOLLYA_BASE_FUNC_LIBRARYFUNCTION:
506
        return "libraryFunction"
507
    elif funcType == SOLLYA_BASE_FUNC_LOG:
508
        return "log"
509
    elif funcType == SOLLYA_BASE_FUNC_LOG_10:
510
        return "log10"
511
    elif funcType == SOLLYA_BASE_FUNC_LOG_1P:
512
        return "log1p"
513
    elif funcType == SOLLYA_BASE_FUNC_LOG_2:
514
        return "log2"
515
    elif funcType == SOLLYA_BASE_FUNC_MUL:
516
        return "*"
517
    elif funcType == SOLLYA_BASE_FUNC_NEARESTINT:
518
        return "round"
519
    elif funcType == SOLLYA_BASE_FUNC_NEG:
520
        return "__neg__"
521
    elif funcType == SOLLYA_BASE_FUNC_PI:
522
        return "pi"
523
    elif funcType == SOLLYA_BASE_FUNC_POW:
524
        return "^"
525
    elif funcType == SOLLYA_BASE_FUNC_PROCEDUREFUNCTION:
526
        return "procedureFunction"
527
    elif funcType == SOLLYA_BASE_FUNC_QUAD:
528
        return "quad"
529
    elif funcType == SOLLYA_BASE_FUNC_SIN:
530
        return "sin"
531
    elif funcType == SOLLYA_BASE_FUNC_SINGLE:
532
        return "single"
533
    elif funcType == SOLLYA_BASE_FUNC_SINH:
534
        return "sinh"
535
    elif funcType == SOLLYA_BASE_FUNC_SQRT:
536
        return "sqrt"
537
    elif funcType == SOLLYA_BASE_FUNC_SUB:
538
        return "-"
539
    elif funcType == SOLLYA_BASE_FUNC_TAN:
540
        return "tan"
541
    elif funcType == SOLLYA_BASE_FUNC_TANH:
542
        return "tanh"
543
    elif funcType == SOLLYA_BASE_FUNC_TRIPLEDOUBLE:
544
        return "tripleDouble"
545
    else:
546
        return None
547

    
548
def pobyso_get_constant(rnArgSa, constSo):
549
    """ Legacy function. See pobyso_get_constant_so_sa. """
550
    return pobyso_get_constant_so_sa(rnArgSa, constSo)
551
# End pobyso_get_constant
552

    
553
def pobyso_get_constant_so_sa(rnArgSa, constSo):
554
    """
555
    Set the value of rnArgSo to the value of constSo in MPFR_RNDN mode.
556
    rnArg must already exist and belong to some RealField.
557
    We assume that constSo points to a Sollya constant.
558
    """
559
    outcome = sollya_lib_get_constant(get_rn_value(rnArgSa), constSo)
560
    if outcome == 0: # Failure because constSo is not a constant expression.
561
        return None
562
    else:
563
        return outcome
564
# End  pobyso_get_constant_so_sa
565
   
566
def pobyso_get_constant_as_rn(ctExpSo):
567
    """ 
568
    Legacy function. See pobyso_get_constant_as_rn_so_sa. 
569
    """ 
570
    return(pobyso_get_constant_as_rn_so_sa(ctExpSo))
571
    
572
def pobyso_get_constant_as_rn_so_sa(constExpSo):
573
    """
574
    Get a Sollya constant as a Sage "real number".
575
    The precision of the floating-point number returned is that of the Sollya
576
    constant.
577
    """
578
    precisionSa  = pobyso_get_prec_of_constant_so_sa(constExpSo)
579
    ## If the expression can not be exactly converted, None is returned.
580
    #  In this case opt for the Sollya current expression.
581
    if precisionSa is None:
582
        precisionSa = pobyso_get_prec_so_sa()
583
    RRRR = RealField(precisionSa)
584
    rnSa = RRRR(0)
585
    outcome = sollya_lib_get_constant(get_rn_value(rnSa), constExpSo)
586
    if outcome == 0:
587
        return None
588
    else:
589
        return rnSa
590
# End pobyso_get_constant_as_rn_so_sa
591

    
592
def pobyso_get_constant_as_rn_with_rf(ctExp, realField):
593
    """ 
594
    Legacy function. See pobyso_get_constant_as_rn_with_rf_so_sa.
595
    """
596
    return pobyso_get_constant_as_rn_with_rf_so_sa(ctExp, realField)
597
# End pobyso_get_constant_as_rn_with_rf
598
    
599
def pobyso_get_constant_as_rn_with_rf_so_sa(ctExpSo, realFieldSa = None):
600
    """
601
    Get a Sollya constant as a Sage "real number".
602
    If no real field is specified, the precision of the floating-point number 
603
    returned is that of the Sollya constant.
604
    Otherwise is is that of the real field. Hence rounding may happen.
605
    """
606
    if realFieldSa is None:
607
        return pobyso_get_constant_as_rn_so_sa(ctExpSo)
608
    rnSa = realFieldSa(0)
609
    outcome = sollya_lib_get_constant(get_rn_value(rnSa), ctExpSo)
610
    if outcome == 0:
611
        return None
612
    else:
613
        return rnSa
614
# End pobyso_get_constant_as_rn_with_rf_so_sa
615

    
616
def pobyso_get_free_variable_name():
617
    """ 
618
    Legacy function. See pobyso_get_free_variable_name_so_sa.
619
    """
620
    return(pobyso_get_free_variable_name_so_sa())
621

    
622
def pobyso_get_free_variable_name_so_sa():
623
    return sollya_lib_get_free_variable_name()
624
    
625
def pobyso_get_function_arity(expressionSo):
626
    """ 
627
    Legacy function. See pobyso_get_function_arity_so_sa.
628
    """
629
    return(pobyso_get_function_arity_so_sa(expressionSo))
630

    
631
def pobyso_get_function_arity_so_sa(expressionSo):
632
    arity = c_int(0)
633
    sollya_lib_get_function_arity(byref(arity),expressionSo)
634
    return int(arity.value)
635

    
636
def pobyso_get_head_function(expressionSo):
637
    """ 
638
    Legacy function. See pobyso_get_head_function_so_sa. 
639
    """
640
    return(pobyso_get_head_function_so_sa(expressionSo)) 
641

    
642
def pobyso_get_head_function_so_sa(expressionSo):
643
    functionType = c_int(0)
644
    sollya_lib_get_head_function(byref(functionType), expressionSo, None)
645
    return int(functionType.value)
646

    
647
def pobyso_get_interval_from_range_so_sa(soRange, realIntervalFieldSa = None ):
648
    """
649
    Return the Sage interval corresponding to the Sollya range argument.
650
    If no reaIntervalField is passed as an argument, the interval bounds are not
651
    rounded: they are elements of RealIntervalField of the "right" precision
652
    to hold all the digits.
653
    """
654
    prec = c_int(0)
655
    if realIntervalFieldSa is None:
656
        retval = sollya_lib_get_prec_of_range(byref(prec), soRange, None)
657
        if retval == 0:
658
            return None
659
        realIntervalFieldSa = RealIntervalField(prec.value)
660
    intervalSa = realIntervalFieldSa(0,0)
661
    retval = \
662
        sollya_lib_get_interval_from_range(get_interval_value(intervalSa),\
663
                                           soRange)
664
    if retval == 0:
665
        return None
666
    return intervalSa
667
# End pobyso_get_interval_from_range_so_sa
668

    
669
def pobyso_get_list_elements(soObj):
670
    """ Legacy function. See pobyso_get_list_elements_so_so. """
671
    return pobyso_get_list_elements_so_so(soObj)
672
 
673
def pobyso_get_list_elements_so_so(objectListSo):
674
    """
675
    Get the Sollya list elements as a Sage/Python array of Sollya objects.
676
    
677
    INPUT:
678
    - objectListSo: a Sollya list of Sollya objects.
679
    
680
    OUTPUT:
681
    - a Sage/Python tuple made of:
682
      - a Sage/Python list of Sollya objects,
683
      - a Sage/Python int holding the number of elements,
684
      - a Sage/Python int stating (!= 0) that the list is end-elliptic.
685
    NOTE::
686
        We recover the addresses of the Sollya object from the list of pointers
687
        returned by sollya_lib_get_list_elements. The list itself is freed.
688
    TODO::
689
        Figure out what to do with numElements since the number of elements
690
        can easily be recovered from the list itself. 
691
        Ditto for isEndElliptic.
692
    """
693
    listAddress = POINTER(c_longlong)()
694
    numElements = c_int(0)
695
    isEndElliptic = c_int(0)
696
    listAsSageList = []
697
    result = sollya_lib_get_list_elements(byref(listAddress),\
698
                                          byref(numElements),\
699
                                          byref(isEndElliptic),\
700
                                          objectListSo)
701
    if result == 0 :
702
        return None
703
    for i in xrange(0, numElements.value, 1):
704
       #listAsSageList.append(sollya_lib_copy_obj(listAddress[i]))
705
       listAsSageList.append(listAddress[i])
706
       # Clear each of the elements returned by Sollya.
707
       #sollya_lib_clear_obj(listAddress[i])
708
    # Free the list itself.   
709
    sollya_lib_free(listAddress)
710
    return (listAsSageList, numElements.value, isEndElliptic.value)
711

    
712
def pobyso_get_max_prec_of_exp(soExp):
713
    """ Legacy function. See pobyso_get_max_prec_of_exp_so_sa. """
714
    return pobyso_get_max_prec_of_exp_so_sa(soExp)
715

    
716
def pobyso_get_max_prec_of_exp_so_sa(expSo):
717
    """
718
    Get the maximum precision used for the numbers in a Sollya expression.
719
    
720
    Arguments:
721
    soExp -- a Sollya expression pointer
722
    Return value:
723
    A Python integer
724
    TODO: 
725
    - error management;
726
    - correctly deal with numerical type such as DOUBLEEXTENDED.
727
    """
728
    maxPrecision = 0
729
    minConstPrec = 0
730
    currentConstPrec = 0
731
    operator = pobyso_get_head_function_so_sa(expSo)
732
    if (operator != SOLLYA_BASE_FUNC_CONSTANT) and \
733
    (operator != SOLLYA_BASE_FUNC_FREE_VARIABLE):
734
        (arity, subexpressions) = pobyso_get_subfunctions_so_sa(expSo)
735
        for i in xrange(arity):
736
            maxPrecisionCandidate = \
737
                pobyso_get_max_prec_of_exp_so_sa(subexpressions[i])
738
            if maxPrecisionCandidate > maxPrecision:
739
                maxPrecision = maxPrecisionCandidate
740
        return maxPrecision
741
    elif operator == SOLLYA_BASE_FUNC_CONSTANT:
742
        #minConstPrec = pobyso_get_min_prec_of_constant_so_sa(expSo)
743
        #currentConstPrec = pobyso_get_min_prec_of_constant_so_sa(soExp)
744
        #print minConstPrec, " - ", currentConstPrec 
745
        return pobyso_get_min_prec_of_constant_so_sa(expSo)
746
    
747
    elif operator == SOLLYA_BASE_FUNC_FREE_VARIABLE:
748
        return 0
749
    else:
750
        print "pobyso_get_max_prec_of_exp_so_sa: unexepected operator."
751
        return 0
752

    
753
def pobyso_get_min_prec_of_constant_so_sa(constExpSo):
754
    """
755
    Get the minimum precision necessary to represent the value of a Sollya
756
    constant.
757
    MPFR_MIN_PREC and powers of 2 are taken into account.
758
    We assume that constExpSo is a pointer to a Sollay constant expression.
759
    """
760
    constExpAsRnSa = pobyso_get_constant_as_rn_so_sa(constExpSo)
761
    return(min_mpfr_size(get_rn_value(constExpAsRnSa)))
762

    
763
def pobyso_get_poly_so_sa(polySo, realFieldSa=None):
764
    """
765
    Convert a Sollya polynomial into a Sage polynomial.
766
    Legacy function. Use pobyso_float_poly_so_sa() instead.
767
    """    
768
    return pobyso_float_poly_so_sa(polySo,realFieldSa)
769
# End pobyso_get_poly_so_sa
770

    
771
def pobyso_get_prec():
772
    """ Legacy function. See pobyso_get_prec_so_sa(). """
773
    return pobyso_get_prec_so_sa()
774

    
775
def pobyso_get_prec_so():
776
    """
777
    Get the current default precision in Sollya.
778
    The return value is a Sollya object.
779
    Usefull when modifying the precision back and forth by avoiding
780
    extra conversions.
781
    """
782
    return sollya_lib_get_prec(None)
783
    
784
def pobyso_get_prec_so_sa():
785
    """
786
    Get the current default precision in Sollya.
787
    The return value is Sage/Python int.
788
    """
789
    precSo = sollya_lib_get_prec(None)
790
    precSa = c_int(0)
791
    sollya_lib_get_constant_as_int(byref(precSa), precSo)
792
    sollya_lib_clear_obj(precSo)
793
    return int(precSa.value)
794
# End pobyso_get_prec_so_sa.
795

    
796
def pobyso_get_prec_so_so_sa():
797
    """
798
    Return the current precision both as a Sollya object and a
799
    Sage integer as hybrid tuple.
800
    To avoid multiple calls for precision manipulations. 
801
    """
802
    precSo = sollya_lib_get_prec(None)
803
    precSa = c_int(0)
804
    sollya_lib_get_constant_as_int(byref(precSa), precSo)
805
    return (precSo, precSa)
806
    
807
def pobyso_get_prec_of_constant(ctExpSo):
808
    """ Legacy function. See pobyso_get_prec_of_constant_so_sa. """
809
    return pobyso_get_prec_of_constant_so_sa(ctExpSo)
810

    
811
def pobyso_get_prec_of_constant_so_sa(ctExpSo):
812
    """
813
    Tries to find a precision to represent ctExpSo without rounding.
814
    If not possible, returns None.
815
    """
816
    prec = c_int(0)
817
    retc = sollya_lib_get_prec_of_constant(byref(prec), ctExpSo, None)
818
    if retc == 0:
819
        return None
820
    return int(prec.value)
821

    
822
def pobyso_get_prec_of_range_so_sa(rangeSo):
823
    """
824
    Returns the number of bits elements of a range are coded with.
825
    """
826
    prec = c_int(0)
827
    retc = sollya_lib_get_prec_of_range(byref(prec), rangeSo, None)
828
    if retc == 0:
829
        return(None)
830
    return int(prec.value)
831
# End pobyso_get_prec_of_range_so_sa()
832

    
833
def pobyso_get_sage_exp_from_sollya_exp(sollyaExpSo, realField = RR):
834
    """ Legacy function. See pobyso_get_sage_exp_from_sollya_exp_so_sa. """
835
    return pobyso_get_sage_exp_from_sollya_exp_so_sa(sollyaExpSo, 
836
                                                     realField = RR)
837

    
838
def pobyso_get_sage_exp_from_sollya_exp_so_sa(sollyaExpSo, realFieldSa = RR):
839
    """
840
    Get a Sage expression from a Sollya expression. 
841
    Currently only tested with polynomials with floating-point coefficients.
842
    Notice that, in the returned polynomial, the exponents are RealNumbers.
843
    """
844
    #pobyso_autoprint(sollyaExp)
845
    operatorSa = pobyso_get_head_function_so_sa(sollyaExpSo)
846
    sollyaLibFreeVariableName = sollya_lib_get_free_variable_name()
847
    ## Get rid of the "_"'s in "_x_", if any.
848
    sollyaLibFreeVariableName = re.sub('_', '', sollyaLibFreeVariableName)
849
    # Constants and the free variable are special cases.
850
    # All other operator are dealt with in the same way.
851
    if (operatorSa != SOLLYA_BASE_FUNC_CONSTANT) and \
852
       (operatorSa != SOLLYA_BASE_FUNC_FREE_VARIABLE):
853
        (aritySa, subexpressionsSa) = pobyso_get_subfunctions_so_sa(sollyaExpSo)
854
        if aritySa == 1:
855
            sageExpSa = eval(pobyso_function_type_as_string_so_sa(operatorSa) + \
856
            "(" + pobyso_get_sage_exp_from_sollya_exp_so_sa(subexpressionsSa[0], \
857
            realFieldSa) + ")")
858
        elif aritySa == 2:
859
            # We do not get through the preprocessor.
860
            # The "^" operator is then a special case.
861
            if operatorSa == SOLLYA_BASE_FUNC_POW:
862
                operatorAsStringSa = "**"
863
            else:
864
                operatorAsStringSa = \
865
                    pobyso_function_type_as_string_so_sa(operatorSa)
866
            sageExpSa = \
867
              eval("pobyso_get_sage_exp_from_sollya_exp_so_sa(subexpressionsSa[0], realFieldSa)"\
868
              + " " + operatorAsStringSa + " " + \
869
                   "pobyso_get_sage_exp_from_sollya_exp_so_sa(subexpressionsSa[1], realFieldSa)")
870
        # We do not know yet how to deal with arity >= 3 
871
        # (is there any in Sollya anyway?).
872
        else:
873
            sageExpSa = eval('None')
874
        return sageExpSa
875
    elif operatorSa == SOLLYA_BASE_FUNC_CONSTANT:
876
        #print "This is a constant"
877
        return pobyso_get_constant_as_rn_with_rf_so_sa(sollyaExpSo, realFieldSa)
878
    elif operatorSa == SOLLYA_BASE_FUNC_FREE_VARIABLE:
879
        #print "This is free variable"
880
        return eval(sollyaLibFreeVariableName)
881
    else:
882
        print "Unexpected"
883
        return eval('None')
884
# End pobyso_get_sage_exp_from_sollya_exp_so_sa
885

    
886

    
887
def pobyso_get_subfunctions(expressionSo):
888
    """ Legacy function. See pobyso_get_subfunctions_so_sa. """
889
    return pobyso_get_subfunctions_so_sa(expressionSo) 
890
# End pobyso_get_subfunctions.
891
 
892
def pobyso_get_subfunctions_so_sa(expressionSo):
893
    """
894
    Get the subfunctions of an expression.
895
    Return the number of subfunctions and the list of subfunctions addresses.
896
    S.T.: Could not figure out another way than that ugly list of declarations
897
    to recover the addresses of the subfunctions.
898
    We limit ourselves to arity 8 functions. 
899
    """
900
    subf0 = c_int(0)
901
    subf1 = c_int(0)
902
    subf2 = c_int(0)
903
    subf3 = c_int(0)
904
    subf4 = c_int(0)
905
    subf5 = c_int(0)
906
    subf6 = c_int(0)
907
    subf7 = c_int(0)
908
    subf8 = c_int(0)
909
    arity = c_int(0)
910
    nullPtr = POINTER(c_int)()
911
    sollya_lib_get_subfunctions(expressionSo, byref(arity), \
912
      byref(subf0), byref(subf1), byref(subf2), byref(subf3), \
913
      byref(subf4), byref(subf5),\
914
      byref(subf6), byref(subf7), byref(subf8), nullPtr, None) 
915
#    byref(cast(subfunctions[0], POINTER(c_int))), \
916
#    byref(cast(subfunctions[0], POINTER(c_int))), \
917
#    byref(cast(subfunctions[2], POINTER(c_int))), \
918
#    byref(cast(subfunctions[3], POINTER(c_int))), \
919
#    byref(cast(subfunctions[4], POINTER(c_int))), \
920
#    byref(cast(subfunctions[5], POINTER(c_int))), \
921
#    byref(cast(subfunctions[6], POINTER(c_int))), \
922
#    byref(cast(subfunctions[7], POINTER(c_int))), \
923
#    byref(cast(subfunctions[8], POINTER(c_int))), nullPtr)
924
    subfunctions = [subf0, subf1, subf2, subf3, subf4, subf5, subf6, subf7, \
925
                    subf8]
926
    subs = []
927
    if arity.value > pobyso_max_arity:
928
        return(0,[])
929
    for i in xrange(arity.value):
930
        subs.append(int(subfunctions[i].value))
931
        #print subs[i]
932
    return (int(arity.value), subs)
933
# End pobyso_get_subfunctions_so_sa
934
    
935
def pobyso_guess_degree_sa_sa(functionSa, intervalSa, approxErrorSa, 
936
                              weightSa=None, degreeBoundSa=None):
937
    """
938
    Sa_sa variant of the solly_guessdegree function.
939
    Return 0 if something goes wrong.
940
    """
941
    functionAsStringSa = functionSa._assume_str().replace('_SAGE_VAR_', '')
942
    functionSo = pobyso_parse_string_sa_so(functionAsStringSa)
943
    if pobyso_is_error_so_sa(functionSo):
944
        sollya_lib_clear_obj(functionSo)
945
        return 0
946
    rangeSo = pobyso_interval_to_range_sa_so(intervalSa)
947
    # The approximation error is expected to be a floating point number.
948
    if pobyso_is_floating_point_number_sa_sa(approxErrorSa):
949
        approxErrorSo = pobyso_constant_sa_so(approxErrorSa)
950
    else:
951
        approxErrorSo = pobyso_constant_sa_so(RR(approxErrorSa))
952
    if not weightSa is None:
953
        weightAsStringSa = weightSa._assume_str().replace('_SAGE_VAR_', '')
954
        weightSo = pobyso_parse_string_sa_so(weightAsStringSa)
955
        if pobyso_is_error_so_sa(weightSo):
956
            sollya_lib_clear_obj(functionSo)
957
            sollya_lib_clear_obj(rangeSo)
958
            sollya_lib_clear_obj(approxErrorSo)   
959
            sollya_lib_clear_obj(weightSo)
960
            return 0   
961
    else:
962
        weightSo = None
963
    if not degreeBoundSa is None:
964
        degreeBoundSo = pobyso_constant_from_int_sa_so(degreeBoundSa)
965
    else:
966
        degreeBoundSo = None
967
    guessedDegreeSa = pobyso_guess_degree_so_sa(functionSo,
968
                                                rangeSo,
969
                                                approxErrorSo,
970
                                                weightSo,
971
                                                degreeBoundSo)
972
    sollya_lib_clear_obj(functionSo)
973
    sollya_lib_clear_obj(rangeSo)
974
    sollya_lib_clear_obj(approxErrorSo)
975
    if not weightSo is None:
976
        sollya_lib_clear_obj(weightSo)
977
    if not degreeBoundSo is None:
978
        sollya_lib_clear_obj(degreeBoundSo)
979
    return guessedDegreeSa
980
# End poyso_guess_degree_sa_sa
981

    
982
def pobyso_guess_degree_so_sa(functionSo, rangeSo, errorSo, weightSo=None, \
983
                              degreeBoundSo=None):
984
    """
985
    Thin wrapper around the guessdegree function.
986
    Nevertheless, some precision control stuff has been appended.
987
    """
988
    # Deal with Sollya internal precision issues: if it is too small, 
989
    # compared with the error, increases it to about twice -log2(error).
990
    errorSa = pobyso_get_constant_as_rn_with_rf_so_sa(errorSo)
991
    log2ErrorSa = errorSa.log2()
992
    if log2ErrorSa < 0:
993
        neededPrecisionSa = int(2 * int(-log2ErrorSa) / 64) * 64
994
    else:
995
        neededPrecisionSa = int(2 * int(log2ErrorSa) / 64) * 64
996
    #print "Needed precision:", neededPrecisionSa
997
    currentPrecSa = pobyso_get_prec_so_sa()
998
    if neededPrecisionSa > currentPrecSa:
999
        currentPrecSo = pobyso_get_prec_so()
1000
        pobyso_set_prec_sa_so(neededPrecisionSa)
1001
    #print "Guessing degree..."
1002
    # weightSo and degreeBoundsSo are optional arguments.
1003
    # As declared, sollya_lib_guessdegree must take 5 arguments.
1004
    if weightSo is None:
1005
        degreeRangeSo = sollya_lib_guessdegree(functionSo, rangeSo, errorSo, 
1006
                                               0, 0, None)
1007
    elif degreeBoundSo is None:
1008
        degreeRangeSo =  sollya_lib_guessdegree(functionSo, rangeSo, \
1009
                                                errorSo, weightSo, 0, None)
1010
    else:
1011
        degreeRangeSo =  sollya_lib_guessdegree(functionSo, rangeSo, errorSo, \
1012
                                                weightSo, degreeBoundSo, None)
1013
    #print "...degree guess done."
1014
    # Restore internal precision, if applicable.
1015
    if neededPrecisionSa > currentPrecSa:
1016
        pobyso_set_prec_so_so(currentPrecSo)
1017
        sollya_lib_clear_obj(currentPrecSo)
1018
    degreeIntervalSa = pobyso_range_to_interval_so_sa(degreeRangeSo)
1019
    sollya_lib_clear_obj(degreeRangeSo)
1020
    # When ok, both bounds match.
1021
    # When the degree bound is too low, the upper bound is the degree
1022
    # for which the error can be honored.
1023
    # When it really goes wrong, the upper bound is infinity. 
1024
    if degreeIntervalSa.lower() == degreeIntervalSa.upper():
1025
        return int(degreeIntervalSa.lower())
1026
    else:
1027
        if degreeIntervalSa.upper().is_infinity():
1028
            return None
1029
        else:
1030
            return int(degreeIntervalSa.upper())
1031
    # End pobyso_guess_degree_so_sa
1032

    
1033
def pobyso_inf_so_so(intervalSo):
1034
    """
1035
    Very thin wrapper around sollya_lib_inf().
1036
    """
1037
    return sollya_lib_inf(intervalSo)
1038
# End pobyso_inf_so_so.
1039
    
1040
def pobyso_infnorm_so_so(func, interval, file = None, intervalList = None):
1041
    print "Do not use this function. User pobyso_supnorm_so_so instead."
1042
    return None
1043

    
1044
def pobyso_interval_to_range_sa_so(intervalSa, precisionSa=None):
1045
    if precisionSa is None:
1046
        precisionSa = intervalSa.parent().precision()
1047
    intervalSo = pobyso_bounds_to_range_sa_so(intervalSa.lower(),\
1048
                                              intervalSa.upper(),\
1049
                                              precisionSa)
1050
    return intervalSo
1051
# End pobyso_interval_to_range_sa_so
1052

    
1053
def pobyso_is_error_so_sa(objSo):
1054
    """
1055
    Thin wrapper around the sollya_lib_obj_is_error() function.
1056
    """
1057
    if sollya_lib_obj_is_error(objSo) != 0:
1058
        return True
1059
    else:
1060
        return False
1061
# End pobyso_is_error-so_sa
1062

    
1063
def pobyso_is_floating_point_number_sa_sa(numberSa):
1064
    """
1065
    Check whether a Sage number is floating point.
1066
    Exception stuff added because numbers other than
1067
    floating-point ones do not have the is_real() attribute.
1068
    """
1069
    try:
1070
        return numberSa.is_real()
1071
    except AttributeError:
1072
        return False
1073
# End pobyso_is_floating_piont_number_sa_sa
1074

    
1075
def pobyso_lib_init():
1076
    sollya_lib_init(None)
1077

    
1078
def pobyso_lib_close():
1079
    sollya_lib_close(None)
1080
    
1081
def pobyso_name_free_variable(freeVariableNameSa):
1082
    """ Legacy function. See pobyso_name_free_variable_sa_so. """
1083
    pobyso_name_free_variable_sa_so(freeVariableNameSa)
1084

    
1085
def pobyso_name_free_variable_sa_so(freeVariableNameSa):
1086
    """
1087
    Set the free variable name in Sollya from a Sage string.
1088
    """
1089
    sollya_lib_name_free_variable(freeVariableNameSa)
1090

    
1091
def pobyso_parse_string(string):
1092
    """ Legacy function. See pobyso_parse_string_sa_so. """
1093
    return pobyso_parse_string_sa_so(string)
1094
 
1095
def pobyso_parse_string_sa_so(string):
1096
    """
1097
    Get the Sollya expression computed from a Sage string or
1098
    a Sollya error object if parsing failed.
1099
    """
1100
    return sollya_lib_parse_string(string)
1101

    
1102
def pobyso_precision_so_sa(ctExpSo):
1103
    """
1104
    Computes the necessary precision to represent a number.
1105
    If x is not zero, it can be uniquely written as x = m · 2e 
1106
    where m is an odd integer and e is an integer. 
1107
    precision(x) returns the number of bits necessary to write m 
1108
    in binary (i.e. ceil(log2(m))).
1109
    """
1110
    #TODO: take care of the special case: 0, @NaN@, @Inf@
1111
    precisionSo = sollya_lib_precision(ctExpSo)
1112
    precisionSa = pobyso_constant_from_int_so_sa(precisionSo)
1113
    sollya_lib_clear_obj(precisionSo)
1114
    return precisionSa
1115
# End pobyso_precision_so_sa
1116

    
1117
def pobyso_polynomial_coefficients_progressive_round_so_so(polySo,
1118
                                                           funcSo,
1119
                                                           icSo,
1120
                                                           intervalSo,
1121
                                                           itpSo,
1122
                                                           ftpSo,
1123
                                                           maxPrecSo,
1124
                                                           maxErrSo):
1125
    print "Input arguments:"
1126
    pobyso_autoprint(polySo)
1127
    pobyso_autoprint(funcSo)
1128
    pobyso_autoprint(icSo)
1129
    pobyso_autoprint(intervalSo)
1130
    pobyso_autoprint(itpSo)
1131
    pobyso_autoprint(ftpSo)
1132
    pobyso_autoprint(maxPrecSo)
1133
    pobyso_autoprint(maxErrSo)
1134
    print "________________"
1135
    
1136
    ## Higher order function see: 
1137
    #  http://effbot.org/pyfaq/how-do-you-make-a-higher-order-function-in-python.htm
1138
    def precision_decay_ratio_function(degreeSa):
1139
        def outer(x):
1140
            def inner(x):
1141
                we = 3/8
1142
                wq = 2/8
1143
                a  = 2.2
1144
                b  = 2 
1145
                return we*(exp(x/a)-1) +  wq*((b*x)**2) + (1-we-wq)*x
1146
            return  inner(x)/inner(degreeSa)
1147
        return outer
1148
    
1149
    #
1150
    degreeSa        = pobyso_polynomial_degree_so_sa(polySo)
1151
    ratio           = precision_decay_ratio_function(degreeSa)
1152
    itpSa           = pobyso_constant_from_int_so_sa(itpSo)
1153
    ftpSa           = pobyso_constant_from_int_so_sa(ftpSo)
1154
    maxPrecSa       = pobyso_constant_from_int_so_sa(maxPrecSo)
1155
    maxErrSa        = pobyso_get_constant_as_rn_so_sa(maxErrSo)
1156
    resPolySo       = pobyso_constant_0_sa_so()
1157
    lastResPolySo   = None
1158
    while True: 
1159
        pDeltaSa    = ftpSa - itpSa
1160
        for indexSa in reversed(xrange(0,degreeSa+1)):
1161
            print "Index:", indexSa
1162
            indexSo = pobyso_constant_from_int_sa_so(indexSa)
1163
            #pobyso_autoprint(indexSo)
1164
            #print ratio(indexSa)
1165
            ctpSa = floor(ftpSa - (pDeltaSa * ratio(indexSa)))
1166
            ctpSo = pobyso_constant_from_int_sa_so(ctpSa)
1167
            print "Index:", indexSa, " - Target precision:", 
1168
            pobyso_autoprint(ctpSo)
1169
            cmonSo  = \
1170
                sollya_lib_build_function_mul(sollya_lib_coeff(polySo, indexSo),
1171
                                      sollya_lib_build_function_pow( \
1172
                                          sollya_lib_build_function_free_variable(), \
1173
                                          indexSo))
1174
            #pobyso_autoprint(cmonSo)
1175
            cmonrSo = pobyso_round_coefficients_single_so_so(cmonSo, ctpSo)
1176
            sollya_lib_clear_obj(cmonSo)
1177
            #pobyso_autoprint(cmonrSo)
1178
            resPolySo = sollya_lib_build_function_add(resPolySo,
1179
                                                      cmonrSo)
1180
            pobyso_autoprint(resPolySo)
1181
        # End for index
1182
        freeVarSo     = sollya_lib_build_function_free_variable()
1183
        changeVarSo   = sollya_lib_sub(freeVarSo, icSo)
1184
        resPolyCvSo   = sollya_lib_evaluate(resPolySo, changeVarSo)
1185
        errFuncSo = sollya_lib_build_function_sub(funcSo, resPolyCvSo)
1186
        infNormSo = sollya_lib_dirtyinform(errFuncSo, intervalSo)
1187
        print "Infnorm (Sollya):", ; pobyso_autoprint(infNormSo)
1188
        cerrSa    = pobyso_get_constant_as_rn_so_sa(infNormSo)
1189
        sollya_lib_clear_obj(resPolyCvSo)
1190
        sollya_lib_clear_obj(infNormSo)
1191
        print "Infnorm  (Sage):", cerrSa
1192
        if (cerrSa > maxErrSa):
1193
            print "Error is too large."
1194
            if not lastResPolySo is None:
1195
                print "Enlarging prec."
1196
                ntpSa = floor(ftpSa + ftpSa/50)
1197
                ## Can't enlarge (numerical)
1198
                if ntpSa == ftpSa:
1199
                    sollya_lib_clear_obj(lastResPolySo)
1200
                    sollya_lib_clear_obj(resPolySo)
1201
                    return None
1202
                ## Can't enlarge (not enough precision left)
1203
                if ntpSa > maxPrecSa:
1204
                    sollya_lib_clear_obj(lastResPolySo)
1205
                    sollya_lib_clear_obj(resPolySo)
1206
                    return None
1207
                ftpSa = ntpSa
1208
                lastResPolySo = resPolySo
1209
                continue
1210
            ## One enlargement took place.
1211
            else:
1212
                sollya_lib_clear_obj(resPolySo)
1213
                return lastResPolySo
1214
        # cerrSa <= maxErrSa: scrap more bits.
1215
        else:
1216
            print "Shrinking prec."
1217
            ntpSa = floor(ftpSa - ftpSa/50)
1218
            ## Can't shrink (numerical)
1219
            if ntpSa == ftpSa:
1220
                if not lastResPolySo is None:
1221
                    sollya_lib_clear_obj(lastResPolySo)
1222
                return resPolySo
1223
            ## Can't enlarge (not enough precision left)
1224
            if ntpSa <= itpSa:
1225
                if not lastResPolySo is None:
1226
                    sollya_lib_clear_obj(lastResPolySo)
1227
                return resPolySo
1228
            ftpSa = ntpSa
1229
            continue
1230
    # End wile True
1231
    return None
1232
# End pobyso_polynomial_coefficients_progressive_truncate_so_so.
1233

    
1234
def pobyso_polynomial_degree_so_sa(polySo):
1235
    """
1236
    Return the degree of a Sollya polynomial as a Sage int.
1237
    """
1238
    degreeSo = sollya_lib_degree(polySo)
1239
    return pobyso_constant_from_int_so_sa(degreeSo)
1240
# End pobyso_polynomial_degree_so_sa
1241

    
1242
def pobyso_polynomial_degree_so_so(polySo):
1243
    """
1244
    Thin wrapper around lib_sollya_degree().
1245
    """
1246
    return sollya_lib_degree(polySo)
1247
# End pobyso_polynomial_degree_so_so
1248
                                                                  
1249
def pobyso_range(rnLowerBound, rnUpperBound):
1250
    """ Legacy function. See pobyso_range_sa_so. """
1251
    return pobyso_range_sa_so(rnLowerBound, rnUpperBound) 
1252

    
1253

    
1254
def pobyso_range_to_interval_so_sa(rangeSo, realIntervalFieldSa = None):
1255
    """
1256
    Get a Sage interval from a Sollya range.
1257
    If no realIntervalField is given as a parameter, the Sage interval
1258
    precision is that of the Sollya range.
1259
    Otherwise, the precision is that of the realIntervalField. In this case
1260
    rounding may happen.
1261
    """
1262
    if realIntervalFieldSa is None:
1263
        precSa = pobyso_get_prec_of_range_so_sa(rangeSo)
1264
        realIntervalFieldSa = RealIntervalField(precSa)
1265
    intervalSa = \
1266
        pobyso_get_interval_from_range_so_sa(rangeSo, realIntervalFieldSa) 
1267
    return intervalSa
1268
# End pobyso_range_to_interval_so_sa
1269

    
1270
def pobyso_rat_poly_sa_so(polySa, precSa = None):
1271
    """
1272
    Create a Sollya polynomial from a Sage rational polynomial.
1273
    """
1274
    ## TODO: filter arguments.
1275
    ## Precision. If no precision is given, use the current precision
1276
    #  of Sollya.
1277
    if precSa is None:
1278
        precSa =  pobyso_get_prec_so_sa()
1279
    #print "Precision:",  precSa
1280
    RRR = RealField(precSa)
1281
    ## Create a Sage polynomial in the "right" precision.
1282
    P_RRR = RRR[polySa.variables()[0]]
1283
    polyFloatSa = P_RRR(polySa)
1284
    ## Make sure no precision is provided: pobyso_float_poly_sa_so will
1285
    #  recover it all by itself and not make an extra conversion.
1286
    return pobyso_float_poly_sa_so(polyFloatSa)
1287
    
1288
# End pobyso_rat_poly_sa_so    
1289
    
1290
def pobyso_remez_canonical_sa_sa(func, \
1291
                                 degree, \
1292
                                 lowerBound, \
1293
                                 upperBound, \
1294
                                 weight = None, \
1295
                                 quality = None):
1296
    """
1297
    All arguments are Sage/Python.
1298
    The functions (func and weight) must be passed as expressions or strings.
1299
    Otherwise the function fails. 
1300
    The return value is a Sage polynomial.
1301
    """
1302
    var('zorglub')    # Dummy variable name for type check only. Type of 
1303
    # zorglub is "symbolic expression".
1304
    polySo = pobyso_remez_canonical_sa_so(func, \
1305
                                 degree, \
1306
                                 lowerBound, \
1307
                                 upperBound, \
1308
                                 weight, \
1309
                                 quality)
1310
    # String test
1311
    if parent(func) == parent("string"):
1312
        functionSa = eval(func)
1313
    # Expression test.
1314
    elif type(func) == type(zorglub):
1315
        functionSa = func
1316
    else:
1317
        return None
1318
    #
1319
    maxPrecision = 0
1320
    if polySo is None:
1321
        return(None)
1322
    maxPrecision = pobyso_get_max_prec_of_exp_so_sa(polySo)
1323
    RRRRSa = RealField(maxPrecision)
1324
    polynomialRingSa = RRRRSa[functionSa.variables()[0]]
1325
    expSa = pobyso_get_sage_exp_from_sollya_exp_so_sa(polySo, RRRRSa)
1326
    polySa = polynomial(expSa, polynomialRingSa)
1327
    sollya_lib_clear_obj(polySo)
1328
    return(polySa)
1329
# End pobyso_remez_canonical_sa_sa
1330
    
1331
def pobyso_remez_canonical(func, \
1332
                           degree, \
1333
                           lowerBound, \
1334
                           upperBound, \
1335
                           weight = "1", \
1336
                           quality = None):
1337
    """ Legacy function. See pobyso_remez_canonical_sa_so. """
1338
    return(pobyso_remez_canonical_sa_so(func, \
1339
                                        degree, \
1340
                                        lowerBound, \
1341
                                        upperBound, \
1342
                                        weight, \
1343
                                        quality))
1344
# End pobyso_remez_canonical.
1345

    
1346
def pobyso_remez_canonical_sa_so(func, \
1347
                                 degree, \
1348
                                 lowerBound, \
1349
                                 upperBound, \
1350
                                 weight = None, \
1351
                                 quality = None):
1352
    """
1353
    All arguments are Sage/Python.
1354
    The functions (func and weight) must be passed as expressions or strings.
1355
    Otherwise the function fails. 
1356
    The return value is a pointer to a Sollya function.
1357
    """
1358
    var('zorglub')    # Dummy variable name for type check only. Type of
1359
    # zorglub is "symbolic expression".
1360
    currentVariableNameSa = None
1361
    # The func argument can be of different types (string, 
1362
    # symbolic expression...)
1363
    if parent(func) == parent("string"):
1364
        localFuncSa = eval(func)
1365
        if len(localFuncSa.variables()) > 0:
1366
            currentVariableNameSa = localFuncSa.variables()[0]
1367
            sollya_lib_name_free_variable(str(currentVariableNameSa))
1368
            functionSo = \
1369
              sollya_lib_parse_string(localFuncSa._assume_str().replace('_SAGE_VAR_', ''))
1370
    # Expression test.
1371
    elif type(func) == type(zorglub):
1372
        # Until we are able to translate Sage expressions into Sollya 
1373
        # expressions : parse the string version.
1374
        if len(func.variables()) > 0:
1375
            currentVariableNameSa = func.variables()[0]
1376
            sollya_lib_name_free_variable(str(currentVariableNameSa))
1377
            functionSo = \
1378
              sollya_lib_parse_string(func._assume_str().replace('_SAGE_VAR_', ''))
1379
    else:
1380
        return(None)
1381
    if weight is None: # No weight given -> 1.
1382
        weightSo = pobyso_constant_1_sa_so()
1383
    elif parent(weight) == parent("string"): # Weight given as string: parse it.
1384
        weightSo = sollya_lib_parse_string(func)
1385
    elif type(weight) == type(zorglub): # Weight given as symbolice expression.
1386
        functionSo = \
1387
          sollya_lib_parse_string_sa_so(weight._assume_str().replace('_SAGE_VAR_', ''))
1388
    else:
1389
        return(None)
1390
    degreeSo = pobyso_constant_from_int(degree)
1391
    rangeSo = pobyso_bounds_to_range_sa_so(lowerBound, upperBound)
1392
    if not quality is None:
1393
        qualitySo= pobyso_constant_sa_so(quality)
1394
    else:
1395
        qualitySo = None
1396
        
1397
    remezPolySo = sollya_lib_remez(functionSo, \
1398
                                   degreeSo, \
1399
                                   rangeSo, \
1400
                                   weightSo, \
1401
                                   qualitySo, \
1402
                                   None)
1403
    sollya_lib_clear_obj(functionSo)
1404
    sollya_lib_clear_obj(degreeSo)
1405
    sollya_lib_clear_obj(rangeSo)
1406
    sollya_lib_clear_obj(weightSo)
1407
    if not qualitySo is None:
1408
        sollya_lib_clear_obj(qualitySo)
1409
    return(remezPolySo)
1410
# End pobyso_remez_canonical_sa_so
1411

    
1412
def pobyso_remez_canonical_so_so(funcSo, \
1413
                                 degreeSo, \
1414
                                 rangeSo, \
1415
                                 weightSo = pobyso_constant_1_sa_so(),\
1416
                                 qualitySo = None):
1417
    """
1418
    All arguments are pointers to Sollya objects.
1419
    The return value is a pointer to a Sollya function.
1420
    """
1421
    if not sollya_lib_obj_is_function(funcSo):
1422
        return(None)
1423
    return(sollya_lib_remez(funcSo, degreeSo, rangeSo, weightSo, qualitySo, None))
1424
# End pobyso_remez_canonical_so_so.
1425

    
1426
def pobyso_round_coefficients_single_so_so(polySo, precSo):
1427
    """
1428
    Create a rounded coefficients polynomial from polynomial argument to
1429
    the number of bits in size argument.
1430
    All coefficients are set to the same precision.
1431
    """
1432
    ## TODO: check arguments.
1433
    endEllipListSo = pobyso_build_end_elliptic_list_so_so(precSo)
1434
    polySo = sollya_lib_roundcoefficients(polySo, endEllipListSo, None)
1435
    sollya_lib_clear_obj(endEllipListSo)
1436
    #sollya_lib_clear_obj(endEllipListSo)
1437
    return polySo
1438
    
1439
# End pobyso_round_coefficients_single_so_so
1440

    
1441
def pobyso_set_canonical_off():
1442
    sollya_lib_set_canonical(sollya_lib_off())
1443

    
1444
def pobyso_set_canonical_on():
1445
    sollya_lib_set_canonical(sollya_lib_on())
1446

    
1447
def pobyso_set_prec(p):
1448
    """ Legacy function. See pobyso_set_prec_sa_so. """
1449
    pobyso_set_prec_sa_so(p)
1450

    
1451
def pobyso_set_prec_sa_so(p):
1452
    a = c_int(p)
1453
    precSo = c_void_p(sollya_lib_constant_from_int(a))
1454
    sollya_lib_set_prec(precSo, None)
1455
# End pobyso_set_prec_sa_so.
1456

    
1457
def pobyso_set_prec_so_so(newPrecSo):
1458
    sollya_lib_set_prec(newPrecSo, None)
1459
# End pobyso_set_prec_so_so.
1460

    
1461
def pobyso_inf_so_so(intervalSo):
1462
    """
1463
    Very thin wrapper around sollya_lib_inf().
1464
    """
1465
    return sollya_lib_inf(intervalSo)
1466
# End pobyso_inf_so_so.
1467
    
1468
def pobyso_supnorm_so_so(polySo, funcSo, intervalSo, errorTypeSo = None,\
1469
                         accuracySo = None):
1470
    """
1471
    Computes the supnorm of the approximation error between the given 
1472
    polynomial and function.
1473
    errorTypeSo defaults to "absolute".
1474
    accuracySo defaults to 2^(-40).
1475
    """
1476
    if errorTypeSo is None:
1477
        errorTypeSo = sollya_lib_absolute(None)
1478
        errorTypeIsNone = True
1479
    else:
1480
        errorTypeIsNone = False
1481
    #
1482
    if accuracySo is None:
1483
        # Notice the **!
1484
        accuracySo = pobyso_constant_sa_so(RR(2**(-40)))
1485
        accuracyIsNone = True
1486
    else:
1487
        accuracyIsNone = False
1488
    pobyso_autoprint(accuracySo)
1489
    resultSo = \
1490
        sollya_lib_supnorm(polySo, funcSo, intervalSo, errorTypeSo, \
1491
                              accuracySo)
1492
    if errorTypeIsNone:
1493
        sollya_lib_clear_obj(errorTypeSo)
1494
    if accuracyIsNone:
1495
        sollya_lib_clear_obj(accuracySo)
1496
    return resultSo
1497
# End pobyso_supnorm_so_so
1498

    
1499
def pobyso_taylor_expansion_no_change_var_so_so(functionSo, 
1500
                                                degreeSo, 
1501
                                                rangeSo,
1502
                                                errorTypeSo=None, 
1503
                                                sollyaPrecSo=None):
1504
    """
1505
    Compute the Taylor expansion without the variable change
1506
    x -> x-intervalCenter.
1507
    """
1508
    # No global change of the working precision.
1509
    if not sollyaPrecSo is None:
1510
        initialPrecSo = sollya_lib_get_prec(None)
1511
        sollya_lib_set_prec(sollyaPrecSo)
1512
    # Error type stuff: default to absolute.
1513
    if errorTypeSo is None:
1514
        errorTypeIsNone = True
1515
        errorTypeSo = sollya_lib_absolute(None)
1516
    else:
1517
        errorTypeIsNone = False
1518
    intervalCenterSo = sollya_lib_mid(rangeSo, None)
1519
    taylorFormSo = sollya_lib_taylorform(functionSo, degreeSo,
1520
                                         intervalCenterSo,
1521
                                         rangeSo, errorTypeSo, None)
1522
    # taylorFormListSaSo is a Python list of Sollya objects references that 
1523
    # are copies of the elements of taylorFormSo.
1524
    # pobyso_get_list_elements_so_so clears taylorFormSo.
1525
    (taylorFormListSaSo, numElementsSa, isEndEllipticSa) = \
1526
        pobyso_get_list_elements_so_so(taylorFormSo)
1527
    polySo = sollya_lib_copy_obj(taylorFormListSaSo[0])
1528
    #print "Num elements:", numElementsSa
1529
    sollya_lib_clear_obj(taylorFormSo)
1530
    #polySo = taylorFormListSaSo[0]
1531
    #errorRangeSo = sollya_lib_copy_obj(taylorFormListSaSo[2])
1532
    errorRangeSo = taylorFormListSaSo[2]
1533
    # No copy_obj needed here: a new objects are created.
1534
    maxErrorSo    = sollya_lib_sup(errorRangeSo)
1535
    minErrorSo    = sollya_lib_inf(errorRangeSo)
1536
    absMaxErrorSo = sollya_lib_abs(maxErrorSo)
1537
    absMinErrorSo = sollya_lib_abs(minErrorSo)
1538
    sollya_lib_clear_obj(maxErrorSo)
1539
    sollya_lib_clear_obj(minErrorSo)
1540
    absMaxErrorSa = pobyso_get_constant_as_rn_so_sa(absMaxErrorSo)
1541
    absMinErrorSa = pobyso_get_constant_as_rn_so_sa(absMinErrorSo)
1542
    # If changed, reset the Sollya working precision.
1543
    if not sollyaPrecSo is None:
1544
        sollya_lib_set_prec(initialPrecSo)
1545
        sollya_lib_clear_obj(initialPrecSo)
1546
    if errorTypeIsNone:
1547
        sollya_lib_clear_obj(errorTypeSo)
1548
    pobyso_clear_taylorform_sa_so(taylorFormListSaSo)
1549
    if absMaxErrorSa > absMinErrorSa:
1550
        sollya_lib_clear_obj(absMinErrorSo)
1551
        return((polySo, intervalCenterSo, absMaxErrorSo))
1552
    else:
1553
        sollya_lib_clear_obj(absMaxErrorSo)
1554
        return((polySo, intervalCenterSo, absMinErrorSo))
1555
# end pobyso_taylor_expansion_no_change_var_so_so
1556

    
1557
def pobyso_taylor_expansion_with_change_var_so_so(functionSo, degreeSo, \
1558
                                                  rangeSo, \
1559
                                                  errorTypeSo=None, \
1560
                                                  sollyaPrecSo=None):
1561
    """
1562
    Compute the Taylor expansion with the variable change
1563
    x -> (x-intervalCenter) included.
1564
    """
1565
    # No global change of the working precision.
1566
    if not sollyaPrecSo is None:
1567
        initialPrecSo = sollya_lib_get_prec(None)
1568
        sollya_lib_set_prec(sollyaPrecSo)
1569
    #
1570
    # Error type stuff: default to absolute.
1571
    if errorTypeSo is None:
1572
        errorTypeIsNone = True
1573
        errorTypeSo = sollya_lib_absolute(None)
1574
    else:
1575
        errorTypeIsNone = False
1576
    intervalCenterSo = sollya_lib_mid(rangeSo)
1577
    taylorFormSo = sollya_lib_taylorform(functionSo, degreeSo, \
1578
                                         intervalCenterSo, \
1579
                                         rangeSo, errorTypeSo, None)
1580
    # taylorFormListSaSo is a Python list of Sollya objects references that 
1581
    # are copies of the elements of taylorFormSo.
1582
    # pobyso_get_list_elements_so_so clears taylorFormSo.
1583
    (taylorFormListSo, numElements, isEndElliptic) = \
1584
        pobyso_get_list_elements_so_so(taylorFormSo)
1585
    polySo = taylorFormListSo[0]
1586
    errorRangeSo = taylorFormListSo[2]
1587
    maxErrorSo    = sollya_lib_sup(errorRangeSo)
1588
    minErrorSo    = sollya_lib_inf(errorRangeSo)
1589
    absMaxErrorSo = sollya_lib_abs(maxErrorSo)
1590
    absMinErrorSo = sollya_lib_abs(minErrorSo)
1591
    sollya_lib_clear_obj(maxErrorSo)
1592
    sollya_lib_clear_obj(minErrorSo)
1593
    absMaxErrorSa = pobyso_get_constant_as_rn_so_sa(absMaxErrorSo)
1594
    absMinErrorSa = pobyso_get_constant_as_rn_so_sa(absMinErrorSo)
1595
    changeVarExpSo = sollya_lib_build_function_sub(\
1596
                       sollya_lib_build_function_free_variable(),\
1597
                       sollya_lib_copy_obj(intervalCenterSo))
1598
    polyVarChangedSo = sollya_lib_evaluate(polySo, changeVarExpSo)
1599
    sollya_lib_clear_obj(polySo) 
1600
    sollya_lib_clear_obj(changeVarExpSo)
1601
    # If changed, reset the Sollya working precision.
1602
    if not sollyaPrecSo is None:
1603
        sollya_lib_set_prec(initialPrecSo)
1604
        sollya_lib_clear_obj(initialPrecSo)
1605
    if errorTypeIsNone:
1606
        sollya_lib_clear_obj(errorTypeSo)
1607
    sollya_lib_clear_obj(taylorFormSo)
1608
    # Do not clear maxErrorSo.
1609
    if absMaxErrorSa > absMinErrorSa:
1610
        sollya_lib_clear_obj(absMinErrorSo)
1611
        return((polyVarChangedSo, intervalCenterSo, absMaxErrorSo))
1612
    else:
1613
        sollya_lib_clear_obj(absMaxErrorSo)
1614
        return((polyVarChangedSo, intervalCenterSo, absMinErrorSo))
1615
# end pobyso_taylor_expansion_with_change_var_so_so
1616

    
1617
def pobyso_taylor(function, degree, point):
1618
    """ Legacy function. See pobysoTaylor_so_so. """
1619
    return(pobyso_taylor_so_so(function, degree, point))
1620

    
1621
def pobyso_taylor_so_so(functionSo, degreeSo, pointSo):
1622
    return(sollya_lib_taylor(functionSo, degreeSo, pointSo))
1623
    
1624
def pobyso_taylorform(function, degree, point = None, 
1625
                      interval = None, errorType=None):
1626
    """ Legacy function. See pobyso_taylorform_sa_sa;"""
1627
    
1628
def pobyso_taylorform_sa_sa(functionSa, \
1629
                            degreeSa, \
1630
                            pointSa, \
1631
                            intervalSa=None, \
1632
                            errorTypeSa=None, \
1633
                            precisionSa=None):
1634
    """
1635
    Compute the Taylor form of 'degreeSa' for 'functionSa' at 'pointSa' 
1636
    for 'intervalSa' with 'errorTypeSa' (a string) using 'precisionSa'. 
1637
    point: must be a Real or a Real interval.
1638
    return the Taylor form as an array
1639
    TODO: take care of the interval and of the point when it is an interval;
1640
          when errorType is not None;
1641
          take care of the other elements of the Taylor form (coefficients 
1642
          errors and delta.
1643
    """
1644
    # Absolute as the default error.
1645
    if errorTypeSa is None:
1646
        errorTypeSo = sollya_lib_absolute()
1647
    elif errorTypeSa == "relative":
1648
        errorTypeSo = sollya_lib_relative()
1649
    elif errortypeSa == "absolute":
1650
        errorTypeSo = sollya_lib_absolute()
1651
    else:
1652
        # No clean up needed.
1653
        return None
1654
    # Global precision stuff
1655
    precisionChangedSa = False
1656
    currentSollyaPrecSo = pobyso_get_prec_so()
1657
    currentSollyaPrecSa = pobyso_constant_from_int_so_sa(currentSollyaPrecSo)
1658
    if not precisionSa is None:
1659
        if precisionSa > currentSollyaPrecSa:
1660
            pobyso_set_prec_sa_so(precisionSa)
1661
            precisionChangedSa = True
1662
            
1663
    if len(functionSa.variables()) > 0:
1664
        varSa = functionSa.variables()[0]
1665
        pobyso_name_free_variable_sa_so(str(varSa))
1666
    # In any case (point or interval) the parent of pointSa has a precision
1667
    # method.
1668
    pointPrecSa = pointSa.parent().precision()
1669
    if precisionSa > pointPrecSa:
1670
        pointPrecSa = precisionSa
1671
    # In any case (point or interval) pointSa has a base_ring() method.
1672
    pointBaseRingString = str(pointSa.base_ring())
1673
    if re.search('Interval', pointBaseRingString) is None: # Point
1674
        pointSo = pobyso_constant_sa_so(pointSa, pointPrecSa)
1675
    else: # Interval.
1676
        pointSo = pobyso_interval_to_range_sa_so(pointSa, pointPrecSa)
1677
    # Sollyafy the function.
1678
    functionSo = pobyso_parse_string_sa_so(functionSa._assume_str().replace('_SAGE_VAR_', ''))
1679
    if sollya_lib_obj_is_error(functionSo):
1680
        print "pobyso_tailorform: function string can't be parsed!"
1681
        return None
1682
    # Sollyafy the degree
1683
    degreeSo = sollya_lib_constant_from_int(int(degreeSa))
1684
    # Sollyafy the point
1685
    # Call Sollya
1686
    taylorFormSo = \
1687
        sollya_lib_taylorform(functionSo, degreeSo, pointSo, errorTypeSo,\
1688
                                         None)
1689
    sollya_lib_clear_obj(functionSo)
1690
    sollya_lib_clear_obj(degreeSo)
1691
    sollya_lib_clear_obj(pointSo)
1692
    sollya_lib_clear_obj(errorTypeSo)
1693
    (tfsAsList, numElements, isEndElliptic) = \
1694
            pobyso_get_list_elements_so_so(taylorFormSo)
1695
    polySo = tfsAsList[0]
1696
    maxPrecision = pobyso_get_max_prec_of_exp_so_sa(polySo)
1697
    polyRealField = RealField(maxPrecision)
1698
    expSa = pobyso_get_sage_exp_from_sollya_exp_so_sa(polySo, polyRealField)
1699
    if precisionChangedSa:
1700
        sollya_lib_set_prec(currentSollyaPrecSo)
1701
        sollya_lib_clear_obj(currentSollyaPrecSo)
1702
    polynomialRing = polyRealField[str(varSa)]
1703
    polySa = polynomial(expSa, polynomialRing)
1704
    taylorFormSa = [polySa]
1705
    # Final clean-up.
1706
    sollya_lib_clear_obj(taylorFormSo)
1707
    return(taylorFormSa)
1708
# End pobyso_taylor_form_sa_sa
1709

    
1710
def pobyso_taylorform_so_so(functionSo, degreeSo, pointSo, intervalSo=None, \
1711
                            errorTypeSo=None):
1712
    createdErrorType = False
1713
    if errorTypeSo is None:
1714
        errorTypeSo = sollya_lib_absolute()
1715
        createdErrorType = True
1716
    else:
1717
        #TODO: deal with the other case.
1718
        pass
1719
    if intervalSo is None:
1720
        resultSo = sollya_lib_taylorform(functionSo, degreeSo, pointSo, \
1721
                                         errorTypeSo, None)
1722
    else:
1723
        resultSo = sollya_lib_taylorform(functionSo, degreeSo, pointSo, \
1724
                                         intervalSo, errorTypeSo, None)
1725
    if createdErrorType:
1726
        sollya_lib_clear_obj(errorTypeSo)
1727
    return resultSo
1728
        
1729

    
1730
def pobyso_univar_polynomial_print_reverse(polySa):
1731
    """ Legacy function. See pobyso_univar_polynomial_print_reverse_sa_sa. """
1732
    return(pobyso_univar_polynomial_print_reverse_sa_sa(polySa))
1733

    
1734
def pobyso_univar_polynomial_print_reverse_sa_sa(polySa):
1735
    """
1736
    Return the string representation of a univariate polynomial with
1737
    monomials ordered in the x^0..x^n order of the monomials.
1738
    Remember: Sage
1739
    """
1740
    polynomialRing = polySa.base_ring()
1741
    # A very expensive solution:
1742
    # -create a fake multivariate polynomial field with only one variable,
1743
    #   specifying a negative lexicographical order;
1744
    mpolynomialRing = PolynomialRing(polynomialRing.base(), \
1745
                                     polynomialRing.variable_name(), \
1746
                                     1, order='neglex')
1747
    # - convert the univariate argument polynomial into a multivariate
1748
    #   version;
1749
    p = mpolynomialRing(polySa)
1750
    # - return the string representation of the converted form.
1751
    # There is no simple str() method defined for p's class.
1752
    return(p.__str__())
1753
#
1754
print pobyso_get_prec()  
1755
pobyso_set_prec(165)
1756
print pobyso_get_prec()  
1757
a=100
1758
print type(a)
1759
id(a)
1760
print "Max arity: ", pobyso_max_arity
1761
print "Function tripleDouble (43) as a string: ", pobyso_function_type_as_string(43)
1762
print "Function None (44) as a string: ", pobyso_function_type_as_string(44)
1763
print "...Pobyso check done"