Statistiques
| Révision :

root / pobysoC-4.0 / src / pobyso.c @ 150

Historique | Voir | Annoter | Télécharger (44,43 ko)

1
/** @file pobyso.c
2
 * Integration of Sollya to C programs
3
 *
4
 * @author S.T.
5
 * @date 2011-10-12
6
 *
7
 * @todo write pobyso_is_monomial function <br>
8
 *       write pobyso_is_free_var_int_poson_power function
9
 */
10
/******************************************************************************/
11
/* Headers, applying the "particular to general" convention.*/
12

    
13
#include "pobyso.h"
14

    
15
/* includes of local headers */
16

    
17
/* includes of project headers */
18

    
19
/* includes of system headers */
20
#include <string.h>
21
#include <stdlib.h>
22
#include <stdio.h>
23

    
24
/* Other declarations */
25

    
26
/* Internal prototypes */
27
void
28
pobyso_error_message(char *functionName, char *messageName, char* message);
29
/* Types, constants and macros definitions */
30

    
31
/* Global variables */
32

    
33
/* Functions */
34

    
35
/* @see pobyso.h#pobyso_autoprint */
36
void
37
pobyso_autoprint(sollya_obj_t objSo)
38
{
39
  sollya_lib_autoprint(objSo, NULL);
40
} /* End pobyso_autoprint. */
41

    
42
/* @see pobyso.h#pobyso_dirty_find_zeros */
43
mpfr_t*
44
pobyso_dirty_find_zeros_bounds(pobyso_func_exp_t funcExpSo,
45
                              mpfr_t lowerBound,
46
                              mpfr_t upperBound,
47
                              int* zerosCount)
48
{
49
  pobyso_range_t rangeSo;
50
  sollya_obj_t zerosListSo    = NULL;
51
  sollya_obj_t* zerosArraySo  = NULL;
52
  mpfr_t* zerosArrayMp        = NULL;
53
  pobyso_precision_t prec;
54

    
55
  int endEll = 0;
56
  int i,j;
57

    
58
  /* Arguments check. */
59
  *zerosCount = -1;
60
  if (funcExpSo == NULL )
61
  {
62
    pobyso_error_message("pobyso_dirty_find_zeros",
63
                        "NULL_POINTER_ARGUMENT",
64
                        "The funcExpSo argument is a NULL pointer");
65
    return NULL;
66
  }
67
  if (mpfr_cmp(lowerBound, upperBound) > 0)
68
  {
69
    pobyso_error_message("pobyso_dirty_find_zeros",
70
                        "INVALID_INTERVAL_ARGUMENT",
71
                        "The lower bound is larger than the upper bound");
72
    return NULL;
73
  }
74
  /* Make a range out of the bounds. */
75
  rangeSo = sollya_lib_range_from_bounds(lowerBound, upperBound);
76
  if (rangeSo == NULL)
77
  {
78
    return NULL;
79
  }
80
  zerosListSo = sollya_lib_dirtyfindzeros(funcExpSo, rangeSo);
81
  if (zerosListSo == NULL)
82
  {
83
    return NULL;
84
  }
85
  sollya_lib_clear_obj(rangeSo);
86
  /* Transform the Sollya list into an MPFR list. */
87
  if (! sollya_lib_get_list_elements(&zerosArraySo,
88
                                      zerosCount,
89
                                      &endEll,
90
                                      zerosListSo))
91
  {
92
    sollya_lib_clear_obj(zerosListSo);
93
    *zerosCount = -1;
94
    return NULL;
95
  }
96
  sollya_lib_clear_obj(zerosListSo);
97
  zerosArrayMp = (mpfr_t*) malloc(*zerosCount * sizeof(mpfr_t));
98
  if (zerosArrayMp == NULL)
99
  {
100
    pobyso_error_message("pobyso_dirty_find_zeros",
101
                          "MEMORY_ALLOCATION_ERROR",
102
                          "Could not allocate zeroes array");
103
    *zerosCount = -1;
104
    return NULL;
105
  }
106
  for (i = 0 ; i < *zerosCount ; i++)
107
  {
108
    if (! sollya_lib_get_prec_of_constant(&prec, zerosArraySo[i]))
109
    {
110
      /* Clean up the already allocated MPFRs. */
111
      for (j = 0 ; j < i ; j++) mpfr_clear(zerosArrayMp[j]);
112
      /* Clean up the zerosArrayMp array itself. */
113
      free(zerosArrayMp);
114
      /* Clean up what is left in the zerosArraySo. */
115
      for (j = i ; j < *zerosCount ; j++) sollya_lib_clear_obj(zerosArraySo[j]);
116
      /* Clean up the zerosArraySo array itself. */
117
      sollya_lib_free(zerosArraySo);
118
      *zerosCount = -1;
119
      return NULL;
120
    }
121
    mpfr_init2(zerosArrayMp[i], prec);
122
    if (! sollya_lib_get_constant(zerosArrayMp[i], zerosArraySo[i]))
123
    {
124
      /* Clean up the already allocated MPFRs. */
125
      for (j = 0 ; j <= i ; j++) mpfr_clear(zerosArrayMp[j]);
126
      /* Clean up the zerosArrayMp array itself. */
127
      free(zerosArrayMp);
128
      /* Clean up what is left in the zerosArraySo. */
129
      for (j = i ; j < *zerosCount ; j++) sollya_lib_clear_obj(zerosArraySo[j]);
130
      /* Clean up the zerosArraySo array itself. */
131
      sollya_lib_free(zerosArraySo);
132
      *zerosCount = -1;
133
      return NULL;
134
    }
135
    sollya_lib_clear_obj(zerosArraySo[i]);
136
  } /* End for i. */
137
  sollya_lib_free(zerosArraySo);
138
  return zerosArrayMp;
139
} /* End pobyso_dirty_find_zeros. */
140

    
141
/* @see pobyso.h#pobyso_evaluate_constant */
142
int
143
pobyso_evaluate_constant(pobyso_func_exp_t functionSo,
144
                          mpfr_t argumentMp,
145
                          mpfr_t evaluationMp)
146
{
147
  sollya_obj_t argumentSo   = NULL;
148
  sollya_obj_t evaluationSo = NULL;
149
  mpfr_t evaluationTmpMp1;
150
  mpfr_t evaluationTmpMp2;
151
  mpfr_prec_t evalPrec      = 0;
152

    
153
  /* Test argument. */
154
  if (functionSo == NULL || argumentMp == NULL || evaluationMp == NULL)
155
  {
156
    pobyso_error_message("pobyso_evaluate_constant",
157
                        "NULL_POINTER_ARGUMENT",
158
                        "One of the arguments is a NULL pointer");
159
    return 1;
160
  }
161
  if (! sollya_lib_obj_is_function(functionSo))
162
  {
163
    pobyso_error_message("pobyso_evaluate_constant",
164
                        "INVALID_TYPE_ARGUMENT",
165
                     "The functionSo argument is not a functional expression");
166
    return 1;
167
  }
168
  /* Function evaluation and checks. */
169
  argumentSo    = sollya_lib_constant(argumentMp);
170
  evaluationSo  = sollya_lib_evaluate(functionSo, argumentSo);
171
  /* Not needed any more. */
172
  //pobyso_autoprint(evaluationSo);
173
  sollya_lib_clear_obj(argumentSo);
174
  /* The range case: we return the mean of the bounds. The result
175
   * is not faithfully rounded. */
176
  if (sollya_lib_obj_is_range(evaluationSo))
177
  {
178
    //pobyso_autoprint(evaluationSo);
179
    if (sollya_lib_get_prec_of_range(&evalPrec, evaluationSo))
180
    {
181
      mpfr_init2(evaluationTmpMp1, evalPrec);
182
      mpfr_init2(evaluationTmpMp2, evalPrec);
183
      if (sollya_lib_get_bounds_from_range(evaluationTmpMp1,
184
                                       evaluationTmpMp2,
185
                                       evaluationSo))
186
      {
187
        /* Compute the mean of the bounds. */
188
        mpfr_clear(evaluationMp);
189
        mpfr_init2(evaluationMp, evalPrec);
190
        mpfr_add(evaluationMp,evaluationTmpMp1,evaluationTmpMp2,MPFR_RNDN);
191
        mpfr_div_2ui(evaluationMp, evaluationMp, 1, MPFR_RNDN);
192
        mpfr_clear(evaluationTmpMp1);
193
        mpfr_clear(evaluationTmpMp2);
194
        sollya_lib_clear_obj(evaluationSo);
195
        /* It may happen, in this case, when the bounds are -Infty  and
196
         * +Infty, that the average is NaN. */
197
        if (mpfr_nan_p(evaluationMp))
198
        {
199
          return POBYSO_NAN;
200
        }
201
        else
202
        {
203
          return POBYSO_UNFAITHFUL;
204
        }
205
      }
206
      else /* Could not get the values of the bounds. */
207
      {
208
        sollya_lib_clear_obj(evaluationSo);
209
        return 1;
210
      }
211
    }
212
    else /* Could not get the precision of the range. */
213
    {
214
      sollya_lib_clear_obj(evaluationSo);
215
      return 1;
216
    }
217
  } /* End the evaluation is a range. */
218
  /* From now on, we assume that the evaluation is constant. */
219
  if (sollya_lib_get_prec_of_constant(&evalPrec, evaluationSo))
220
  {
221
    mpfr_init2(evaluationTmpMp1, evalPrec);
222
    if (sollya_lib_get_constant(evaluationTmpMp1, evaluationSo))
223
    {
224
      /* Deal with the NaN case. */
225
      if (mpfr_nan_p(evaluationTmpMp1))
226
      {
227
        mpfr_clear(evaluationTmpMp1);
228
        sollya_lib_clear_obj(evaluationSo);
229
        return POBYSO_NAN;
230
      }
231
      else /* The evaluation is not NaN. */
232
      {
233
        mpfr_clear(evaluationMp);
234
        mpfr_init2(evaluationMp, evalPrec);
235
        mpfr_set(evaluationMp, evaluationTmpMp1, MPFR_RNDN);
236
        mpfr_clear(evaluationTmpMp1);
237
        sollya_lib_clear_obj(evaluationSo);
238
        return 0;
239
      }
240
    }
241
    else /* Could not recover the value of the evaluation. */
242
    {
243
      mpfr_clear(evaluationTmpMp1);
244
      sollya_lib_clear_obj(evaluationSo);
245
      return 1;
246
    }
247
  }
248
  else /* Could not get the precision of the evaluation. */
249
  {
250
    sollya_lib_clear_obj(evaluationSo);
251
    return 0;
252
  }
253
}
254
/* End pobyso_evaluate_constant. */
255

    
256
/* @see pobyso.h#pobyso_get_verbosity */
257
int
258
pobyso_get_verbosity()
259
{
260
  sollya_obj_t verbositySo = NULL;
261
  int verbosity            = 0;
262

    
263
  verbositySo = sollya_lib_get_verbosity();
264
  sollya_lib_get_constant_as_int(&verbosity,verbositySo);
265
  sollya_lib_clear_obj(verbositySo);
266
  return verbosity;
267
} /* End pobyso_get_verbosity. */
268

    
269
/** @see pobyso.h#pobyso_is_constant_expression
270
 * Strategy: rely on sollya_lib_get_constant. It return 1, when the
271
 * expression is constant.
272
 */
273
int
274
pobyso_is_constant_expression(sollya_obj_t obj_to_test)
275
{
276
  mpfr_t dummy;
277
  int test;
278
  int initial_verbosity_level      = 0;
279

    
280
  /* Test argument. */
281
  if (obj_to_test == NULL)
282
  {
283
    pobyso_error_message("pobyso_is_constant_expression",
284
                        "NULL_POINTER_ARGUMENT",
285
                        "The expression is a NULL pointer");
286
    return 0;
287
  }
288
  initial_verbosity_level = pobyso_set_verbosity_off();
289
  /* In Sollya, constant are functional expressions. */
290
  if (! sollya_lib_obj_is_function(obj_to_test))
291
  {
292
    pobyso_set_verbosity_to(initial_verbosity_level);
293
    return 0;
294
  }
295
  mpfr_init2(dummy,64);
296
  /* Call to previous Sollya function resets verbosity. */
297
  /* Todo: change verbosity suppression strategy with a message call back. */
298
  pobyso_set_verbosity_off();
299
  /* Try to convert the would be constant into an MPFR number. */
300
  /* If OK, we indeed have a constant. If the conversion fails, return 0. */
301
  test = sollya_lib_get_constant(dummy, obj_to_test);
302
  pobyso_set_verbosity_to(initial_verbosity_level);
303
  if (test)
304
  {
305
    if(mpfr_number_p(dummy) || mpfr_inf_p(dummy))
306
    {
307
      mpfr_clear(dummy);
308
      return test;
309
    }
310
    else /* We do not consider NaNs as constants. */
311
    {
312
      mpfr_clear(dummy);
313
      return 0;
314
    }
315
  }
316
  else
317
  {
318
    mpfr_clear(dummy);
319
    return 0;
320
  }
321
} /* End pobyso_is_constant_expression. */
322

    
323
/** @see pobyso.h#pobyso_is_monomial. */
324
int
325
pobyso_is_int(pobyso_func_exp_t exprSo)
326
{
327
  mpfr_t float1M;
328
  mpfr_t float2M;
329
  mpfr_t tempFloat1M;
330
  mpfr_t tempFloat2M;
331
  mpfr_prec_t prec;
332
  int64_t asInt;
333
  sollya_obj_t newConstantSo = NULL;
334
  /* Arguments check. */
335
  if (exprSo == NULL)
336
  {
337
    pobyso_error_message("pobyso_is_free_var_posze_int_power",
338
                        "NULL_POINTER_ARGUMENT",
339
                        "The expression is a NULL pointer");
340
    return 0;
341
  }
342
  //fprintf(stdout, "Not NULL.\n"); pobyso_autoprint(exprSo);
343
  if (! pobyso_is_constant_expression(exprSo)) return 0;
344
  if (! sollya_lib_get_constant_as_int64(&asInt, exprSo)) return 0;
345
  if (asInt == INT64_MIN || asInt == INT64_MAX) return 0;
346
  /* Some constant integer expression can't have their precision computed
347
   * (e.g. cos(pi). */
348
  if (! sollya_lib_get_prec_of_constant(&prec, exprSo))
349
  {
350
    mpfr_init2(tempFloat1M, 165);
351
    mpfr_init2(tempFloat2M, 165);
352
    mpfr_abs(tempFloat1M, tempFloat1M, MPFR_RNDN);
353
    mpfr_log2(tempFloat2M, tempFloat1M, MPFR_RNDU);
354
    mpfr_rint_ceil(tempFloat1M, tempFloat2M, MPFR_RNDU);
355
    prec = mpfr_get_si(tempFloat1M, MPFR_RNDN) + 10;
356
    if (prec < 1024) prec = 1024;
357
    mpfr_clear(tempFloat1M);
358
    mpfr_clear(tempFloat2M);
359
    mpfr_init2(float1M, prec);
360
    if (!sollya_lib_get_constant(float1M, exprSo))
361
    {
362
      mpfr_clear(float1M);
363
      return 0;
364
    }
365
  }
366
  else /* Precision could be given. */
367
  {
368
    mpfr_init2(float1M, prec);
369
    if (! sollya_lib_get_constant(float1M, exprSo))
370
    {
371
      mpfr_clear(float1M);
372
      return 0;
373
    }
374
  }
375
  if (mpfr_nan_p(float1M) || mpfr_inf_p(float1M))
376
  {
377
    mpfr_clear(float1M);
378
    return 0;
379
  }
380
  if ((newConstantSo = sollya_lib_constant_from_int64(asInt)) == NULL)
381
  {
382
    mpfr_clear(float1M);
383
    return 0;
384
  }
385
  sollya_lib_get_prec_of_constant(&prec, newConstantSo);
386
  mpfr_init2(float2M, prec);
387
  sollya_lib_get_constant(float2M, newConstantSo);
388
  if (mpfr_cmp(float1M, float2M) == 0)
389
  {
390
    mpfr_clear(float1M);
391
    mpfr_clear(float2M);
392
    sollya_lib_clear_obj(newConstantSo);
393
    return 1;
394
  }
395
  else
396
  {
397
    mpfr_clear(float1M);
398
    mpfr_clear(float2M);
399
    sollya_lib_clear_obj(newConstantSo);
400
    return 0;
401
  }
402
} /* End pobyso_is_int. */
403

    
404
/** @see pobyso.h#pobyso_is_monomial.
405
 * Strategy: check that the object is a functional expression and
406
 * if so check that it is made of cte * free_var ^ some_power where :
407
 * - cte is a constant expression (a per pobyso_is_constant_experession;
408
 * - some_power is a positive or null power. t*/
409
int
410
pobyso_is_monomial(sollya_obj_t objSo)
411
{
412
  int arity;
413
  sollya_obj_t subFun1So = NULL;
414
  sollya_obj_t subFun2So = NULL;
415
  sollya_obj_t subFun3So = NULL;
416
  sollya_base_function_t head = 0;
417
  long int exponent = 0;
418
  long int exprIntValue = 0;
419

    
420
  /* Arguments check. */
421
  if (objSo == NULL)
422
  {
423
    pobyso_error_message("pobyso_is_monomial",
424
                        "NULL_POINTER_ARGUMENT",
425
                        "The expression is a NULL pointer");
426
    return 0;
427
  }
428
  /* The object must be a function. */
429
  if (! sollya_lib_obj_is_function(objSo)) return 0;
430
  /* Check if it is the 1 constant. */
431
  if (pobyso_is_int(objSo))
432
  {
433
    if (! sollya_lib_get_constant_as_int64(&exprIntValue, objSo))
434
    {
435
      return 0;
436
    }
437
    else
438
    {
439
      if (exprIntValue == 1) return 1;
440
      else return 0;
441
    }
442
  }
443
  if (! sollya_lib_decompose_function(objSo,
444
                                      &head,
445
                                      &arity,
446
                                      &subFun1So,
447
                                      &subFun2So,
448
                                      NULL)) return 0;
449
  if (arity > 2)
450
  {
451
    if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
452
    if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
453
    return 0;
454
  }
455
  /* Arity == 1 must be free variable by itself. */
456
  if (arity == 1 && head == SOLLYA_BASE_FUNC_FREE_VARIABLE)
457
  {
458
    if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
459
    if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
460
    return 1;
461
  }
462
  else
463
  {
464
    /* Another expression. Must be: free variable  ^ poze integer. */
465
    if (arity == 2)
466
    {
467
      if (head != SOLLYA_BASE_FUNC_POW)
468
      {
469
        if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
470
        if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
471
        return 0;
472
      }
473
      if (! pobyso_is_int(subFun2So))
474
      {
475
        if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
476
        if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
477
        return 0;
478
      }
479
      if (! sollya_lib_get_constant_as_int64(&exponent, subFun2So))
480
      {
481
        if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
482
        if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
483
        return 0;
484
      }
485
      if (exponent < 0)
486
      {
487
        if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
488
        if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
489
        return 0;
490
      }
491
      if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
492
      /* Check that the first subfunction is the free variable. */
493
      if (! sollya_lib_decompose_function(subFun1So,
494
                                          &head,
495
                                          &arity,
496
                                          &subFun2So,
497
                                          &subFun3So,
498
                                          NULL))
499
      {
500
        if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
501
        return 0;
502
      }
503
      if (arity == 1 && head == SOLLYA_BASE_FUNC_FREE_VARIABLE)
504
      {
505
        if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
506
        if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
507
        if (subFun3So != NULL) sollya_lib_clear_obj(subFun3So);
508
        return 1;
509
      }
510
      else
511
      {
512
        if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
513
        if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
514
        return 0;
515
      }
516
    } /* End if arity == 2. */
517
  } /* End else if arity == 1. */
518
  return 0;
519
} /* End pobyso_is_monomial. */
520

    
521
/** @see pobyso.h#pobyso_is_polynomial_term.
522
 * Strategy: check that the object is a functional expression and
523
 * if so check that it is made of cte * monomial.
524
 */
525
int
526
pobyso_is_polynomial_term(sollya_obj_t objSo)
527
{
528
  int arity;
529
  sollya_obj_t subFun1So = NULL;
530
  sollya_obj_t subFun2So = NULL;
531
  sollya_base_function_t head = 0;
532

    
533
  /* Arguments check. */
534
  if (objSo == NULL)
535
  {
536
    pobyso_error_message("pobyso_is_polynomial_term",
537
                        "NULL_POINTER_ARGUMENT",
538
                        "The expression is a NULL pointer");
539
    return 0;
540
  }
541
  /* The object must be a function. */
542
  if (! sollya_lib_obj_is_function(objSo)) return 0;
543
  /* A constant expression is degree 0 polynomial term. */
544
  if (pobyso_is_constant_expression(objSo)) return 1;
545
  /* A monomial is a polynomial term. */
546
  if (pobyso_is_monomial(objSo)) return 1;
547
  /* Decompose the functional expression and study the elements. */
548
  if (! sollya_lib_decompose_function(objSo,
549
                                      &head,
550
                                      &arity,
551
                                      &subFun1So,
552
                                      &subFun2So,
553
                                      NULL)) return 0;
554
  /* Monomial case has been dealt with abobe. */
555
  if (arity != 2)
556
  {
557
    if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
558
    if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
559
    return 0;
560
  }
561
  /* The expression must be: cte  * monomial or monomial * cte. */
562
  if (head != SOLLYA_BASE_FUNC_MUL)
563
  {
564
    if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
565
    if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
566
    return 0;
567
  }
568
  if (! pobyso_is_monomial(subFun2So))
569
  {
570
    if (! pobyso_is_constant_expression(subFun2So) ||
571
        ! pobyso_is_monomial(subFun1So))
572
    {
573
      if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
574
      if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
575
      return 0;
576
    }
577
  }
578
  else
579
  {
580
    if (! pobyso_is_constant_expression(subFun1So))
581
    {
582
      if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
583
      if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
584
      return 0;
585
    }
586
  }
587
  return 1;
588
} /* End pobyso_is_polynomial_term. */
589
/** @see pobyso.h#pobyso_new_monomial. */
590
pobyso_func_exp_t
591
pobyso_new_monomial(pobyso_func_exp_t coefficientSo, long degree)
592
{
593
  sollya_obj_t degreeSo   = NULL;
594
  sollya_obj_t varToPowSo = NULL;
595
  sollya_obj_t monomialSo = NULL;
596
  int initial_verbosity_level = 0;
597

    
598
  /* Arguments check. */
599
  if (coefficientSo == NULL)
600
  {
601
    pobyso_error_message("pobyso_parse_string",
602
                        "NULL_POINTER_ARGUMENT",
603
                        "The expression is a NULL pointer");
604
    return NULL;
605
  }
606
  if (! pobyso_is_constant_expression(coefficientSo))
607
  {
608
    return NULL;
609
  }
610
  if (degree < 0)
611
  {
612
    pobyso_error_message("pobyso_new_monomial",
613
                        "NEGATIVE_DEGREE_ARGUMENT",
614
                        "The degree is a negative integer");
615
    return NULL;
616
  }
617
  /* If degree == 0, just return a copy of the coefficient. Do not
618
   * return the coefficient itself to avoid "double clear" issues. */
619
  if (degree == 0)
620
  {
621
    initial_verbosity_level = pobyso_set_verbosity_off();
622
    monomialSo = sollya_lib_copy_obj(coefficientSo);
623
    pobyso_set_verbosity_to(initial_verbosity_level);
624
  }
625
  degreeSo    = sollya_lib_constant_from_int64(degree);
626
  varToPowSo  = sollya_lib_build_function_pow(sollya_lib_free_variable(),
627
                                              degreeSo);
628
  /* Do not use the "build" version to avoid "eating up" the coefficient. */
629
  monomialSo = sollya_lib_mul(coefficientSo,varToPowSo);
630
  sollya_lib_clear_obj(varToPowSo);
631
  /* Do not clear degreeSa: it was "eaten" by sollya-lib_build_function. */
632
  return monomialSo;
633
} /* End pobyso_new_monomial. */
634

    
635
/* @see pobyso.h#pobyso_off */
636
pobyso_on_off_t
637
pobyso_off()
638
{
639
  return sollya_lib_off();
640
} /* End pobyso_off. */
641

    
642
/* @see pobyso.h#pobyso_off */
643
pobyso_on_off_t
644
pobyso_on()
645
{
646
  return sollya_lib_on();
647
} /* End pobyso_on. */
648

    
649

    
650
/* @see pobyso.h#pobyso_parse_string */
651
pobyso_func_exp_t
652
pobyso_parse_string(const char* expression)
653
{
654
  int expressionLength, i;
655
  char *expressionWithSemiCo;
656
  sollya_obj_t expressionSo;
657

    
658
  /* Arguments check. */
659
  if (expression == NULL)
660
  {
661
    pobyso_error_message("pobyso_parse_string",
662
                        "NULL_POINTER_ARGUMENT",
663
                        "The expression is a NULL pointer");
664
    return  NULL;
665
  }
666
  expressionLength = strlen(expression);
667
  if (expressionLength == 0)
668
  {
669
    pobyso_error_message("pobyso_parse_string",
670
                        "EMPTY_STRING_ARGUMENT",
671
                        "The expression is an empty string");
672
    return NULL;
673
  }
674
  /* Search from the last char of the expression until, whichever happens
675
   * first:
676
   * a ";" is found;
677
   * a char  != ';' is found the the ";" is appended.
678
   * If the head of the string is reached before any of these two events happens
679
   * return an error.
680
   */
681
  for (i = expressionLength - 1 ; i >= 0 ; i--)
682
  {
683
    if (expression[i] == ';') /* Nothing special to do:
684
                                 try to parse the string*/
685
    {
686
      expressionSo = sollya_lib_parse_string(expression);
687
      if (sollya_lib_obj_is_error(expressionSo))
688
      {
689
        sollya_lib_clear_obj(expressionSo);
690
        return NULL;
691
      }
692
      else
693
      {
694
        return expressionSo;
695
      }
696
    }
697
    else
698
    {
699
      if (expression[i] == ' ' || expression[i] == '\t') /* A blank,
700
                                                           just continue. */
701
      {
702
        continue;
703
      }
704
      else /* a character != ';' and from a blank: create the ';'ed string. */
705
      {
706
        /* Create a new string for the expression, add the ";" and
707
         * and call sollya_lib_parse_string. */
708
        expressionWithSemiCo = calloc(i + 3, sizeof(char));
709
        if (expressionWithSemiCo == NULL)
710
        {
711
          pobyso_error_message("pobyso_parse_string",
712
                                "MEMORY_ALLOCATION_ERROR",
713
                                "Could not allocate the expression string");
714
          return NULL;
715
        }
716
        strncpy(expressionWithSemiCo, expression, i+1);
717
        expressionWithSemiCo[i + 1] = ';';
718
        expressionWithSemiCo[i + 2] = '\0';
719
        expressionSo = sollya_lib_parse_string(expressionWithSemiCo);
720
        free(expressionWithSemiCo);
721
        if (sollya_lib_obj_is_error(expressionSo))
722
        {
723
          sollya_lib_clear_obj(expressionSo);
724
          return NULL;
725
        }
726
        else
727
        {
728
          return expressionSo;
729
        }
730
      } /* End character != ';' and from a blank. */
731
    /* Create a new string for the expression, add the ";" and
732
     * and call sollya_lib_parse_string. */
733
    } /* End else. */
734
  } /* End for. */
735
  /* We get here, it is because we did not find any char == anything different
736
   * from ' ' or '\t': the string is empty.
737
   */
738
  pobyso_error_message("pobyso_parse_string",
739
                       "ONLY_BLANK_ARGUMENT",
740
                        "The expression is only made of blanks");
741
  return NULL;
742
} /* pobyso_parse_string */
743

    
744
pobyso_constant_t
745
pobyso_quiet()
746
{
747
  pobyso_constant_t verbositySo = NULL;
748
  pobyso_constant_t zeroSo      = NULL;
749

    
750
  verbositySo = sollya_lib_get_verbosity();
751
  zeroSo = sollya_lib_constant_from_int64(0);
752
  if (zeroSo != NULL)
753
  {
754
    sollya_lib_set_verbosity(zeroSo);
755
    sollya_lib_clear_obj(zeroSo);
756
    return verbositySo;
757
  }
758
  else
759
  {
760
    sollya_lib_clear_obj(verbositySo);
761
    return NULL;
762
  }
763

    
764
} /* End pobyso_quiet. */
765

    
766
/** @see pobyso.h#pobyso_range_from_bounds */
767
pobyso_range_t
768
pobyso_range_from_bounds(mpfr_t lowerBound, mpfr_t upperBound)
769
{
770
  /* Supferficial check of arguments. */
771
  if (mpfr_cmp(lowerBound, upperBound) > 0)
772
  {
773
      return(NULL);
774
  }
775
  return(sollya_lib_range_from_bounds(lowerBound, upperBound));
776
}
777

    
778
pobyso_func_exp_t
779
pobyso_remez_canonical_monomials_base(pobyso_func_exp_t function,
780
                                      long int degree,
781
                                      pobyso_range_t interval,
782
                                      pobyso_func_exp_t weight,
783
                                      double quality,
784
                                      pobyso_range_t bounds)
785
{
786
  sollya_obj_t  degreeSo = NULL;
787
  sollya_obj_t qualitySo = NULL;
788

    
789
  degreeSo = sollya_lib_constant_from_int(degree);
790
  qualitySo = sollya_lib_constant_from_double(quality);
791

    
792
  sollya_lib_clear_obj(degreeSo);
793
  sollya_lib_clear_obj(qualitySo);
794
  return NULL;
795
} /* End pobyso_remez_canonical_monomials_base. */
796

    
797
int
798
pobyso_set_canonical_on()
799
{
800
  pobyso_on_off_t currentCanonicalModeSo;
801
  pobyso_on_off_t on;
802

    
803
  currentCanonicalModeSo = sollya_lib_get_canonical();
804
  if (sollya_lib_is_on(currentCanonicalModeSo))
805
  {
806
    sollya_lib_clear_obj(currentCanonicalModeSo);
807
    return POBYSO_ON;
808
  }
809
  else
810
  {
811
    on = sollya_lib_on();
812
    sollya_lib_set_canonical(on);
813
    sollya_lib_clear_obj(on);
814
    sollya_lib_clear_obj(currentCanonicalModeSo);
815
    return POBYSO_OFF;
816
  }
817
} /* End pobyso_set_canonical_on. */
818

    
819
int
820
pobyso_set_verbosity_off()
821
{
822
  sollya_obj_t verbosityLevelZeroSo;
823
  sollya_obj_t currentVerbosityLevelSo = NULL;
824
  int currentVerbosityLevel = 0;
825

    
826
  currentVerbosityLevelSo = sollya_lib_get_verbosity();
827
  sollya_lib_get_constant_as_int(&currentVerbosityLevel,
828
                                 currentVerbosityLevelSo);
829
  verbosityLevelZeroSo = sollya_lib_constant_from_int(0);
830
  sollya_lib_set_verbosity(verbosityLevelZeroSo);
831
  sollya_lib_clear_obj(verbosityLevelZeroSo);
832
  sollya_lib_clear_obj(currentVerbosityLevelSo);
833
  return currentVerbosityLevel;
834
} /* End of pobyso_set_verbosity_off. */
835

    
836
int
837
pobyso_set_verbosity_to(int newVerbosityLevel)
838
{
839
  int initialVerbosityLevel = 0;
840
  sollya_obj_t initialVerbosityLevelSo = NULL;
841
  sollya_obj_t newVerbosityLevelSo = NULL;
842

    
843
  initialVerbosityLevelSo = sollya_lib_get_verbosity();
844
  sollya_lib_get_constant_as_int(&initialVerbosityLevel,
845
                                 initialVerbosityLevelSo);
846
  sollya_lib_clear_obj(initialVerbosityLevelSo);
847
  if (newVerbosityLevel < 0)
848
  {
849
    pobyso_error_message("pobyso_set_verbosity_to",
850
                        "INVALID_VALUE",
851
                        "The new verbosity level is a negative number");
852
    return initialVerbosityLevel;
853
  }
854
  newVerbosityLevelSo = sollya_lib_constant_from_int(newVerbosityLevel);
855
  sollya_lib_set_verbosity(newVerbosityLevelSo);
856
  sollya_lib_clear_obj(newVerbosityLevelSo);
857
  return initialVerbosityLevel;
858
} /* End of pobyso_set_verbosity_to. */
859

    
860
/**
861
 * @see pobyso.h#pobyso_subpoly
862
 */
863
pobyso_func_exp_t
864
pobyso_subpoly(pobyso_func_exp_t polynomialSo, long expsNum, long int* expsList)
865
{
866
  sollya_obj_t  expsListSo    = NULL;
867
  sollya_obj_t* expsList_pso  = NULL;
868
  sollya_obj_t subpoly        = NULL;
869
  int i, j;
870

    
871
  /* Arguments check. */
872
  if (polynomialSo == NULL) return NULL;
873
  if (expsNum < 0) return NULL;
874
  if (expsNum == 0) return sollya_lib_copy_obj(polynomialSo);
875
  if (expsList == 0) return NULL;
876
  /* Create a list of Sollya constants. */
877
  expsList_pso = (sollya_obj_t*) malloc(expsNum * sizeof(sollya_obj_t));
878
  if (expsList_pso == NULL)
879
  {
880
    pobyso_error_message("pobyso_subpoly",
881
                          "MEMORY_ALLOCATION_ERROR",
882
                          "Could not allocate the Sollya exponents list");
883
    return NULL;
884
  }
885
  /* Fill up the list. */
886
  for (i = 0 ; i < expsNum ; i++)
887
  {
888
    /* Abort if an exponent is negative. */
889
    if (expsList[i] < 0 )
890
    {
891
      for (j = 0 ; j < i ; j++)
892
      {
893
        sollya_lib_clear_obj(expsList_pso[j]);
894
      }
895
      free(expsList_pso);
896
      return NULL;
897
    }
898
    expsList_pso[i] = sollya_lib_constant_from_int64(expsList[i]);
899
  } /* End for */
900
  expsListSo = sollya_lib_list(expsList_pso, expsNum);
901
  for (i = 0 ; i < expsNum ; i++)
902
  {
903
    sollya_lib_clear_obj(expsList_pso[i]);
904
  }
905
  free(expsList_pso);
906
  if (expsListSo == NULL)
907
  {
908
    pobyso_error_message("pobyso_subpoly",
909
                          "LIST_CREATIONERROR",
910
                          "Could not create the exponents list");
911
    return NULL;
912
  }
913
  subpoly = sollya_lib_subpoly(polynomialSo, expsListSo);
914
  pobyso_autoprint(expsListSo);
915
  sollya_lib_clear_obj(expsListSo);
916
  return subpoly;
917
} /* pobyso_subpoly. */
918

    
919
/* Attic from the sollya_lib < 4. */
920
#if 0
921
chain*
922
pobyso_create_canonical_monomials_base(const unsigned int degree)
923
{
924
  int i    = 0;
925
  chain *monomials  = NULL;
926
  node  *monomial   = NULL;
927

928
  for(i = degree ; i >= 0  ; i--)
929
  {
930
     monomial   = makePow(makeVariable(), makeConstantDouble((double)i));
931
     monomials  = addElement(monomials, monomial);
932
     fprintf(stderr, "pobyso_create_canonical_monomials_base: %u\n", i);
933
  }
934
  if (monomials == NULL)
935
  {
936
    pobyso_error_message("pobyso_create_canonical_monomial_base",
937
                        "CHAIN_CREATION_ERROR",
938
                        "Could not create the monomials chain");
939
    return(NULL);
940
  }
941
  return(monomials);
942
} /* End pobyso_create_canonical_monomials_base. */
943

944
chain*
945
pobyso_create_chain_from_int_array(int* intArray,
946
                                    const unsigned int arrayLength)
947
{
948
  int i = 0;
949
  chain *newChain = NULL;
950
  int *currentInt;
951

952
  if (arrayLength == 0) return(NULL);
953
  if (intArray == NULL)
954
  {
955
    pobyso_error_message("pobyso_create_chain_from_int_array",
956
                        "NULL_POINTER_ARGUMENT",
957
                        "The array is a NULL pointer");
958
    return(NULL);
959
  }
960
  for (i = arrayLength - 1 ; i >= 0 ; i--)
961
  {
962
    currentInt = malloc(sizeof(int));
963
    if (currentInt == NULL)
964
    {
965
      pobyso_error_message("pobyso_create_chain_from_int_array",
966
                          "MEMORY_ALLOCATION_ERROR",
967
                          "Could not allocate one of the integers");
968
      freeChain(newChain, free);
969
      return(NULL);
970
    }
971
    *currentInt = intArray[i];
972
    newChain = addElement(newChain, currentInt);
973
  }
974
  return(newChain);
975
} // End pobyso_create_chain_from_int_array. */
976

977
chain*
978
pobyso_create_chain_from_unsigned_int_array(unsigned int* intArray,
979
                                        const unsigned int arrayLength)
980
{
981
  int i = 0;
982
  chain *newChain = NULL;
983
  unsigned int *currentInt;
984

985
  /* Argument checking. */
986
  if (arrayLength == 0) return(NULL);
987
  if (intArray == NULL)
988
  {
989
    pobyso_error_message("pobyso_create_chain_from_unsigned_int_array",
990
                        "NULL_POINTER_ARGUMENT",
991
                        "The array is a NULL pointer");
992
    return(NULL);
993
  }
994
  for (i = arrayLength - 1 ; i >= 0 ; i--)
995
  {
996
    currentInt = malloc(sizeof(unsigned int));
997
    if (currentInt == NULL)
998
    {
999
      pobyso_error_message("pobyso_create_chain_from_unsigned_int_array",
1000
                          "MEMORY_ALLOCATION_ERROR",
1001
                          "Could not allocate one of the integers");
1002
      freeChain(newChain, free);
1003
      return(NULL);
1004
    }
1005
    *currentInt = intArray[i];
1006
    newChain = addElement(newChain, currentInt);
1007
  }
1008
  return(newChain);
1009
} // End pobyso_create_chain_from_unsigned_int_array. */
1010

1011
node*
1012
pobyso_differentiate(node *functionNode)
1013
{
1014
  /* Argument checking. */
1015
  node *differentialNode;
1016
  if (functionNode == NULL)
1017
  {
1018
    pobyso_error_message("pobyso_differentiate",
1019
                        "NULL_POINTER_ARGUMENT",
1020
                        "The function to differentiate is a NULL pointer");
1021
    return(NULL);
1022
  }
1023
  differentialNode = differentiate(functionNode);
1024
  if (differentialNode == NULL)
1025
  {
1026
    pobyso_error_message("pobyso_differentiate",
1027
                        "INTERNAL ERROR",
1028
                        "Sollya could not differentiate the function");
1029
  }
1030
  return(differentialNode);
1031
} // End pobyso_differentiate
1032

1033

1034
int
1035
pobyso_dirty_infnorm(mpfr_t infNorm,
1036
                      node *functionNode,
1037
                      mpfr_t lowerBound,
1038
                      mpfr_t upperBound,
1039
                      mp_prec_t precision)
1040
{
1041
  int functionCallResult;
1042
  /* Arguments checking. */
1043
  if (functionNode == NULL)
1044
  {
1045
    pobyso_error_message("pobyso_dirty_infnorm",
1046
                        "NULL_POINTER_ARGUMENT",
1047
                        "The function to compute is a NULL pointer");
1048
    return(1);
1049
  }
1050
  if (mpfr_cmp(lowerBound, upperBound) > 0)
1051
  {
1052
    pobyso_error_message("pobyso_dirty_infnorm",
1053
                        "INCOHERENT_INPUT_DATA",
1054
                        "The lower bond is greater than the upper bound");
1055
    return(1);
1056
  }
1057
  /* Particular cases. */
1058
  if (mpfr_cmp(lowerBound, upperBound) == 0)
1059
  {
1060
    functionCallResult = pobyso_evaluate_faithful(infNorm,
1061
                                                  functionNode,
1062
                                                  lowerBound,
1063
                                                  precision);
1064
    return(functionCallResult);
1065
  }
1066
  if (isConstant(functionNode))
1067
  {
1068
    functionCallResult = pobyso_evaluate_faithful(infNorm,
1069
                                                  functionNode,
1070
                                                  lowerBound,
1071
                                                  precision);
1072
    if (!functionCallResult)
1073
    {
1074
      mpfr_abs(infNorm, infNorm, MPFR_RNDN);
1075
    }
1076
    return(functionCallResult);
1077
  }
1078
  uncertifiedInfnorm(infNorm,
1079
                      functionNode,
1080
                      lowerBound,
1081
                      upperBound,
1082
                      POBYSO_DEFAULT_POINTS,
1083
                      precision);
1084
  return(0);
1085
} /* End pobyso_dirty_infnorm. */
1086

1087
int
1088
pobyso_evaluate_faithful(mpfr_t faithfulEvaluation,
1089
                          node *nodeToEvaluate,
1090
                          mpfr_t argument,
1091
                          mpfr_prec_t precision)
1092
{
1093
  /* Check input arguments. */
1094
  if (nodeToEvaluate == NULL)
1095
  {
1096
    pobyso_error_message("pobyso_evaluate_faithful",
1097
                        "NULL_POINTER_ARGUMENT",
1098
                        "nodeToEvaluate is a NULL pointer");
1099
    return(1);
1100
  }
1101
  evaluateFaithful(faithfulEvaluation,
1102
                   nodeToEvaluate,
1103
                   argument,
1104
                   precision);
1105
  return(0);
1106
} /* End pobyso_evaluate_faithfull. */
1107

1108
chain*
1109
pobyso_find_zeros(node *function,
1110
                  mpfr_t *lower_bound,
1111
                  mpfr_t *upper_bound)
1112
{
1113
  mp_prec_t currentPrecision;
1114
  mpfr_t currentDiameter;
1115
  rangetype bounds;
1116

1117
  currentPrecision = getToolPrecision();
1118
  mpfr_init2(currentDiameter, currentPrecision);
1119

1120
  bounds.a = lower_bound;
1121
  bounds.b = upper_bound;
1122

1123
  if (bounds.a == NULL || bounds.b == NULL)
1124
  {
1125
    pobyso_error_message("pobyso_find_zeros",
1126
                        "MEMORY_ALLOCATION_ERROR",
1127
                        "Could not allocate one of the bounds");
1128
    return(NULL);
1129
  }
1130
  return(findZerosFunction(function,
1131
                            bounds,
1132
                            currentPrecision,
1133
                            currentDiameter));
1134
} /* End pobyso_find_zeros. */
1135

1136
void
1137
pobyso_free_chain_of_nodes(chain *theChainOfNodes)
1138
{
1139
  node *currentNode           = NULL;
1140
  chain *currentChainElement  = NULL;
1141
  chain *nextChainElement     = NULL;
1142

1143
  nextChainElement = theChainOfNodes;
1144

1145
  while(nextChainElement != NULL)
1146
  {
1147
    currentChainElement = nextChainElement;
1148
    currentNode = (node*)(currentChainElement->value);
1149
    nextChainElement = nextChainElement->next;
1150
    free_memory(currentNode);
1151
    free((void*)(currentChainElement));
1152
  }
1153
} /* End pobyso_free_chain_of_nodes. */
1154

1155
void
1156
pobyso_free_range(rangetype range)
1157
{
1158

1159
  mpfr_clear(*(range.a));
1160
  mpfr_clear(*(range.b));
1161
  free(range.a);
1162
  free(range.b);
1163
} /* End pobyso_free_range. */
1164

1165
node*
1166
pobyso_fp_minimax_canonical_monomials_base(node *function,
1167
                                      int degree,
1168
                                      chain *formats,
1169
                                      chain *points,
1170
                                      mpfr_t lowerBound,
1171
                                      mpfr_t upperBound,
1172
                                      int fpFixedArg,
1173
                                      int absRel,
1174
                                      node *constPart,
1175
                                      node *minimax)
1176
{
1177
  return(NULL);
1178
} /* End pobyso_fp_minimax_canonical_monomials_base. */
1179

1180
node*
1181
pobyso_parse_function(char *functionString,
1182
                      char *freeVariableNameString)
1183
{
1184
  if (functionString == NULL || freeVariableNameString == NULL)
1185
  {
1186
    pobyso_error_message("pobyso_parse_function",
1187
                        "NULL_POINTER_ARGUMENT",
1188
                        "One of the arguments is a NULL pointer");
1189
    return(NULL);
1190
  }
1191
  return(parseString(functionString));
1192

1193
} /* End pobyso_parse_function */
1194

1195
node*
1196
pobyso_remez_approx_canonical_monomials_base_for_error(node *functionNode,
1197
                                                  unsigned int mode,
1198
                                                  mpfr_t lowerBound,
1199
                                                  mpfr_t upperBound,
1200
                                                  mpfr_t eps)
1201
{
1202
  node *weight              = NULL;
1203
  node *bestApproxPolyNode  = NULL;
1204
  node *bestApproxHorner    = NULL;
1205
  node *errorNode           = NULL;
1206
  rangetype degreeRange;
1207
  mpfr_t quality;
1208
  mpfr_t currentError;
1209
  unsigned int degree;
1210

1211
  /* Check the parameters. */
1212
  if (functionNode == NULL)
1213
  {
1214
    pobyso_error_message("remezApproxCanonicalMonomialsBaseForError",
1215
                        "NULL_POINTER_ARGUMENT",
1216
                        "functionNode is a NULL pointer");
1217
    return(NULL);
1218
  }
1219
  if (mpfr_cmp(lowerBound, upperBound) >= 0)
1220
  {
1221
    pobyso_error_message("remezApproxCanonicalMonomialsBaseForError",
1222
                        "INCOHERENT_INPUT_DATA",
1223
                        "the lower_bound >= upper_bound");
1224
    return(NULL);
1225
  }
1226
  /* Set the weight. */
1227
  if (mode == POBYSO_ABSOLUTE)
1228
  {
1229
    /* Set the weight to 1 for the ABSOLUTE_MODE. */
1230
    weight = makeConstantDouble(1.0);
1231
  }
1232
  else
1233
  {
1234
    if (mode == POBYSO_RELATIVE)
1235
    {
1236
      pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
1237
                          "NOT_IMPLEMENTED",
1238
                          "the search for relative error is not implemented yet");
1239
      return(NULL);
1240
    }
1241
    else
1242
    {
1243
      pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
1244
                          "INCOHERENT_INPUT_DATA",
1245
                          "the mode is node of POBYSO_ABOLUTE or POBYSO_RELATIVE");
1246
      return(NULL);
1247
    }
1248
  }
1249
  //fprintf(stderr, "\n\n\n******* I'm here! ********\n\n\n");
1250
  degreeRange = guessDegree(functionNode,
1251
                            weight,
1252
                            lowerBound,
1253
                            upperBound,
1254
                            eps,
1255
                            POBYSO_GUESS_DEGREE_BOUND);
1256
  degree = mpfr_get_ui(*(degreeRange.a), MPFR_RNDN);
1257
  //fprintf(stderr, "\n\n\n******* I'm back! ********\n\n\n");
1258
  fprintf(stderr, "Guessed degree: ");
1259
  mpfr_out_str(stderr, 10, 17, *(degreeRange.a), MPFR_RNDN);
1260
  fprintf(stderr, " - as int: %u\n", degree);
1261
  /* Reduce the degree by 1 in the foolish hope it could work. */
1262
  if (degree > 0) degree--;
1263
  /* Both elements of degreeRange where "inited" within guessDegree. */
1264
  mpfr_clear(*(degreeRange.a));
1265
  mpfr_clear(*(degreeRange.b));
1266
  free(degreeRange.a);
1267
  free(degreeRange.b);
1268
  /* Mimic the default behavior of interactive Sollya. */
1269
  mpfr_init(quality);
1270
  mpfr_set_d(quality, 1e-5, MPFR_RNDN);
1271
  mpfr_init2(currentError, getToolPrecision());
1272
  mpfr_set_inf(currentError,1);
1273

1274
  /* Try to refine the initial guess: loop with increasing degrees until
1275
   * we find a satisfactory one. */
1276
  while(mpfr_cmp(currentError, eps) > 0)
1277
  {
1278
    /* Get rid of the previous polynomial, if any. */
1279
    if (bestApproxPolyNode != NULL)
1280
    {
1281
      free_memory(bestApproxPolyNode);
1282
    }
1283
    fprintf(stderr, "Degree: %u\n", degree);
1284
    fprintf(stderr, "Calling pobyso_remez_canonical_monomials_base...\n");
1285
    /* Try to find a polynomial with the guessed degree. */
1286
    bestApproxPolyNode = pobyso_remez_canonical_monomials_base(functionNode,
1287
                                                            weight,
1288
                                                            degree,
1289
                                                            lowerBound,
1290
                                                            upperBound,
1291
                                                            quality);
1292

1293
    if (bestApproxPolyNode == NULL)
1294
    {
1295
      pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
1296
                          "INTERNAL_ERROR",
1297
                          "could not compute the bestApproxPolyNode");
1298
      mpfr_clear(currentError);
1299
      mpfr_clear(quality);
1300
      return(NULL);
1301
    }
1302

1303
    setDisplayMode(DISPLAY_MODE_DECIMAL);
1304
    fprintTree(stderr, bestApproxPolyNode);
1305
    fprintf(stderr, "\n\n");
1306

1307
    errorNode = makeSub(copyTree(functionNode), copyTree(bestApproxPolyNode));
1308
    /* Check the error with the computed polynomial. */
1309
    uncertifiedInfnorm(currentError,
1310
                        errorNode,
1311
                        lowerBound,
1312
                        upperBound,
1313
                        POBYSO_INF_NORM_NUM_POINTS,
1314
                        getToolPrecision());
1315
    fprintf(stderr, "Inf norm: ");
1316
    mpfr_out_str(stderr, 10, 17, currentError, MPFR_RNDN);
1317
    fprintf(stderr, "\n\n");
1318
    /* Free the errorNode but not the bestApproxPolyNode (we need it if
1319
     * we exit the loop at the next iteration). */
1320
    free_memory(errorNode);
1321
    degree++;
1322
  }
1323
  /* Use an intermediate variable, since horner() creates a new node
1324
   * and does not reorder the argument "in place". This allows for the memory
1325
   * reclaim of bestApproxHorner.
1326
   */
1327
  bestApproxHorner = horner(bestApproxPolyNode);
1328
  free_memory(bestApproxPolyNode);
1329
  mpfr_clear(currentError);
1330
  mpfr_clear(quality);
1331
  free_memory(weight);
1332
  return(bestApproxHorner);
1333
} /* End pobyso_remez_approx_canonical_monomials_base_for_error */
1334

1335
node*
1336
pobyso_remez_canonical_monomials_base(node *function,
1337
                                     node *weight,
1338
                                     unsigned int degree,
1339
                                     mpfr_t lowerBound,
1340
                                     mpfr_t upperBound,
1341
                                     mpfr_t quality)
1342
{
1343
  node  *bestApproxPoly = NULL;
1344
  chain *monomials      = NULL;
1345
  chain *curMonomial    = NULL;
1346

1347
  mpfr_t satisfying_error;
1348
  mpfr_t target_error;
1349

1350
  /* Argument checking */
1351
  /* Function tree. */
1352
  if (function == NULL)
1353
  {
1354
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
1355
                        "NULL_POINTER_ARGUMENT",
1356
                        "the \"function\" argument is a NULL pointer");
1357
    return(NULL);
1358
  }
1359
  if (weight == NULL)
1360
  {
1361
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
1362
                        "NULL_POINTER_ARGUMENT",
1363
                        "the \"weight\" argument is a NULL pointer");
1364
    return(NULL);
1365
  }
1366
  /* Check the bounds. */
1367
  if (mpfr_cmp(lowerBound, upperBound) >= 0)
1368
  {
1369
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
1370
                        "INCOHERENT_IMPUT_DATA",
1371
                        "the lower_bound >= upper_bound");
1372
    return(NULL);
1373
  }
1374
  /* The quality must be a non null positive number. */
1375
  if (mpfr_sgn(quality) <= 0)
1376
  {
1377
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
1378
                        "INCOHERENT_INPUT_DATA",
1379
                        "the quality <= 0");
1380
  }
1381
  /* End argument checking. */
1382
  /* Create the monomials nodes chains. */
1383
  monomials = pobyso_create_canonical_monomials_base(degree);
1384
  fprintf(stderr, "monomials chain length = %d\n", lengthChain(monomials));
1385
  if (monomials == NULL || (lengthChain(monomials) != degree + 1))
1386
  {
1387
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
1388
                        "CHAIN_CREATION_ERROR",
1389
                        "could not create the monomials chain");
1390
    return(NULL);
1391
  }
1392
  curMonomial = monomials;
1393

1394
  while (curMonomial != NULL)
1395
  {
1396
    fprintf(stderr, "monomial tree: ");
1397
    //mpfr_out_str(stderr, 10, 17, *((mpfr_t*)((node*)(curMonomial->value))->value), MPFR_RNDN);
1398
    fprintTree(stderr, (node*)(curMonomial->value));
1399
    fprintf(stderr, "\n");
1400
    curMonomial = curMonomial->next;
1401
  }
1402

1403
  /* Deal with NULL weight. */
1404
  if (weight == NULL)
1405
  {
1406
    weight = makeConstantDouble(1.0);
1407
  }
1408
  /* Compute the best polynomial with the required quality.
1409
     The behavior is as if satisfying error and target_error had
1410
     not been used.*/
1411
  mpfr_init(satisfying_error);
1412
  mpfr_init(target_error);
1413
  mpfr_set_str(satisfying_error, "0", 10, MPFR_RNDN);
1414
  mpfr_set_inf(target_error, 1);
1415

1416

1417
  fprintf(stderr, "satisfying_error: ");
1418
  mpfr_out_str(stderr, 10, 17, satisfying_error, MPFR_RNDN);
1419
  fprintf(stderr, ".\n");
1420
  fprintf(stderr, "target_error: ");
1421
  mpfr_out_str(stderr, 10, 17, target_error,MPFR_RNDN);
1422
  fprintf(stderr, ".\n");
1423

1424
  fprintf(stderr,
1425
          "current precision: %li\n", getToolPrecision());
1426
  /* Call the Sollya function. */
1427
  bestApproxPoly = remez(function,
1428
                          weight,
1429
                          monomials,
1430
                          lowerBound,
1431
                          upperBound,
1432
                          quality,
1433
                          satisfying_error,
1434
                          target_error,
1435
                          getToolPrecision());
1436

1437
  mpfr_clear(satisfying_error);
1438
  mpfr_clear(target_error);
1439
  pobyso_free_chain_of_nodes(monomials);
1440

1441
  return(bestApproxPoly);
1442
} /* End pobyso_remez_canonical_monomials_base. */
1443

1444
#endif
1445

    
1446
void
1447
pobyso_error_message(char *functionName, char *messageName, char* message)
1448
{
1449
  fprintf(stderr, "?%s: %s.\n%s.\n", functionName, messageName, message);
1450
} /* End pobyso_error_message */