Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (44,6 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_clear_obj */
43
void
44
pobyso_clear_obj(sollya_obj_t objSo)
45
{
46
  if (objSo == NULL) {return;}
47
  sollya_lib_clear_obj(objSo);
48
} /* End  pobyso_clear_obj. */
49

    
50
/* @see pobyso.h#pobyso_dirty_find_zeros */
51
mpfr_t*
52
pobyso_dirty_find_zeros_bounds(pobyso_func_exp_t funcExpSo,
53
                              mpfr_t lowerBound,
54
                              mpfr_t upperBound,
55
                              int* zerosCount)
56
{
57
  pobyso_range_t rangeSo;
58
  sollya_obj_t zerosListSo    = NULL;
59
  sollya_obj_t* zerosArraySo  = NULL;
60
  mpfr_t* zerosArrayMp        = NULL;
61
  pobyso_precision_t prec;
62

    
63
  int endEll = 0;
64
  int i,j;
65

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

    
149
/* @see pobyso.h#pobyso_evaluate_constant */
150
int
151
pobyso_evaluate_constant(pobyso_func_exp_t functionSo,
152
                          mpfr_t argumentMp,
153
                          mpfr_t evaluationMp)
154
{
155
  sollya_obj_t argumentSo   = NULL;
156
  sollya_obj_t evaluationSo = NULL;
157
  mpfr_t evaluationTmpMp1;
158
  mpfr_t evaluationTmpMp2;
159
  mpfr_prec_t evalPrec      = 0;
160

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

    
264
/* @see pobyso.h#pobyso_get_verbosity */
265
int
266
pobyso_get_verbosity()
267
{
268
  sollya_obj_t verbositySo = NULL;
269
  int verbosity            = 0;
270

    
271
  verbositySo = sollya_lib_get_verbosity();
272
  sollya_lib_get_constant_as_int(&verbosity,verbositySo);
273
  sollya_lib_clear_obj(verbositySo);
274
  return verbosity;
275
} /* End pobyso_get_verbosity. */
276

    
277
/** @see pobyso.h#pobyso_is_constant_expression
278
 * Strategy: rely on sollya_lib_get_constant. It return 1, when the
279
 * expression is constant.
280
 */
281
int
282
pobyso_is_constant_expression(sollya_obj_t obj_to_test)
283
{
284
  mpfr_t dummy;
285
  int test;
286
  int initial_verbosity_level      = 0;
287

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

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

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

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

    
529
/** @see pobyso.h#pobyso_is_polynomial_term.
530
 * Strategy: check that the object is a functional expression and
531
 * if so check that it is made of cte * monomial.
532
 */
533
int
534
pobyso_is_polynomial_term(sollya_obj_t objSo)
535
{
536
  int arity;
537
  sollya_obj_t subFun1So = NULL;
538
  sollya_obj_t subFun2So = NULL;
539
  sollya_base_function_t head = 0;
540

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

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

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

    
650
/* @see pobyso.h#pobyso_off */
651
pobyso_on_off_t
652
pobyso_on()
653
{
654
  return sollya_lib_on();
655
} /* End pobyso_on. */
656

    
657

    
658
/* @see pobyso.h#pobyso_parse_string */
659
pobyso_func_exp_t
660
pobyso_parse_string(const char* expression)
661
{
662
  int expressionLength, i;
663
  char *expressionWithSemiCo;
664
  sollya_obj_t expressionSo;
665

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

    
752
pobyso_constant_t
753
pobyso_quiet()
754
{
755
  pobyso_constant_t verbositySo = NULL;
756
  pobyso_constant_t zeroSo      = NULL;
757

    
758
  verbositySo = sollya_lib_get_verbosity();
759
  zeroSo = sollya_lib_constant_from_int64(0);
760
  if (zeroSo != NULL)
761
  {
762
    sollya_lib_set_verbosity(zeroSo);
763
    sollya_lib_clear_obj(zeroSo);
764
    return verbositySo;
765
  }
766
  else
767
  {
768
    sollya_lib_clear_obj(verbositySo);
769
    return NULL;
770
  }
771

    
772
} /* End pobyso_quiet. */
773

    
774
/** @see pobyso.h#pobyso_range_from_bounds */
775
pobyso_range_t
776
pobyso_range_from_bounds(mpfr_t lowerBound, mpfr_t upperBound)
777
{
778
  /* Supferficial check of arguments. */
779
  if (mpfr_cmp(lowerBound, upperBound) > 0)
780
  {
781
      return(NULL);
782
  }
783
  return(sollya_lib_range_from_bounds(lowerBound, upperBound));
784
}
785

    
786
pobyso_func_exp_t
787
pobyso_remez_canonical_monomials_base(pobyso_func_exp_t function,
788
                                      long int degree,
789
                                      pobyso_range_t interval,
790
                                      pobyso_func_exp_t weight,
791
                                      double quality,
792
                                      pobyso_range_t bounds)
793
{
794
  sollya_obj_t  degreeSo = NULL;
795
  sollya_obj_t qualitySo = NULL;
796

    
797
  degreeSo = sollya_lib_constant_from_int(degree);
798
  qualitySo = sollya_lib_constant_from_double(quality);
799

    
800
  sollya_lib_clear_obj(degreeSo);
801
  sollya_lib_clear_obj(qualitySo);
802
  return NULL;
803
} /* End pobyso_remez_canonical_monomials_base. */
804

    
805
int
806
pobyso_set_canonical_on()
807
{
808
  pobyso_on_off_t currentCanonicalModeSo;
809
  pobyso_on_off_t on;
810

    
811
  currentCanonicalModeSo = sollya_lib_get_canonical();
812
  if (sollya_lib_is_on(currentCanonicalModeSo))
813
  {
814
    sollya_lib_clear_obj(currentCanonicalModeSo);
815
    return POBYSO_ON;
816
  }
817
  else
818
  {
819
    on = sollya_lib_on();
820
    sollya_lib_set_canonical(on);
821
    sollya_lib_clear_obj(on);
822
    sollya_lib_clear_obj(currentCanonicalModeSo);
823
    return POBYSO_OFF;
824
  }
825
} /* End pobyso_set_canonical_on. */
826

    
827
int
828
pobyso_set_verbosity_off()
829
{
830
  sollya_obj_t verbosityLevelZeroSo;
831
  sollya_obj_t currentVerbosityLevelSo = NULL;
832
  int currentVerbosityLevel = 0;
833

    
834
  currentVerbosityLevelSo = sollya_lib_get_verbosity();
835
  sollya_lib_get_constant_as_int(&currentVerbosityLevel,
836
                                 currentVerbosityLevelSo);
837
  verbosityLevelZeroSo = sollya_lib_constant_from_int(0);
838
  sollya_lib_set_verbosity(verbosityLevelZeroSo);
839
  sollya_lib_clear_obj(verbosityLevelZeroSo);
840
  sollya_lib_clear_obj(currentVerbosityLevelSo);
841
  return currentVerbosityLevel;
842
} /* End of pobyso_set_verbosity_off. */
843

    
844
int
845
pobyso_set_verbosity_to(int newVerbosityLevel)
846
{
847
  int initialVerbosityLevel = 0;
848
  sollya_obj_t initialVerbosityLevelSo = NULL;
849
  sollya_obj_t newVerbosityLevelSo = NULL;
850

    
851
  initialVerbosityLevelSo = sollya_lib_get_verbosity();
852
  sollya_lib_get_constant_as_int(&initialVerbosityLevel,
853
                                 initialVerbosityLevelSo);
854
  sollya_lib_clear_obj(initialVerbosityLevelSo);
855
  if (newVerbosityLevel < 0)
856
  {
857
    pobyso_error_message("pobyso_set_verbosity_to",
858
                        "INVALID_VALUE",
859
                        "The new verbosity level is a negative number");
860
    return initialVerbosityLevel;
861
  }
862
  newVerbosityLevelSo = sollya_lib_constant_from_int(newVerbosityLevel);
863
  sollya_lib_set_verbosity(newVerbosityLevelSo);
864
  sollya_lib_clear_obj(newVerbosityLevelSo);
865
  return initialVerbosityLevel;
866
} /* End of pobyso_set_verbosity_to. */
867

    
868
/**
869
 * @see pobyso.h#pobyso_subpoly
870
 */
871
pobyso_func_exp_t
872
pobyso_subpoly(pobyso_func_exp_t polynomialSo, long expsNum, long int* expsList)
873
{
874
  sollya_obj_t  expsListSo    = NULL;
875
  sollya_obj_t* expsList_pso  = NULL;
876
  sollya_obj_t subpoly        = NULL;
877
  int i, j;
878

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

    
927
/* Attic from the sollya_lib < 4. */
928
#if 0
929
chain*
930
pobyso_create_canonical_monomials_base(const unsigned int degree)
931
{
932
  int i    = 0;
933
  chain *monomials  = NULL;
934
  node  *monomial   = NULL;
935

936
  for(i = degree ; i >= 0  ; i--)
937
  {
938
     monomial   = makePow(makeVariable(), makeConstantDouble((double)i));
939
     monomials  = addElement(monomials, monomial);
940
     fprintf(stderr, "pobyso_create_canonical_monomials_base: %u\n", i);
941
  }
942
  if (monomials == NULL)
943
  {
944
    pobyso_error_message("pobyso_create_canonical_monomial_base",
945
                        "CHAIN_CREATION_ERROR",
946
                        "Could not create the monomials chain");
947
    return(NULL);
948
  }
949
  return(monomials);
950
} /* End pobyso_create_canonical_monomials_base. */
951

952
chain*
953
pobyso_create_chain_from_int_array(int* intArray,
954
                                    const unsigned int arrayLength)
955
{
956
  int i = 0;
957
  chain *newChain = NULL;
958
  int *currentInt;
959

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

985
chain*
986
pobyso_create_chain_from_unsigned_int_array(unsigned int* intArray,
987
                                        const unsigned int arrayLength)
988
{
989
  int i = 0;
990
  chain *newChain = NULL;
991
  unsigned int *currentInt;
992

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

1019
node*
1020
pobyso_differentiate(node *functionNode)
1021
{
1022
  /* Argument checking. */
1023
  node *differentialNode;
1024
  if (functionNode == NULL)
1025
  {
1026
    pobyso_error_message("pobyso_differentiate",
1027
                        "NULL_POINTER_ARGUMENT",
1028
                        "The function to differentiate is a NULL pointer");
1029
    return(NULL);
1030
  }
1031
  differentialNode = differentiate(functionNode);
1032
  if (differentialNode == NULL)
1033
  {
1034
    pobyso_error_message("pobyso_differentiate",
1035
                        "INTERNAL ERROR",
1036
                        "Sollya could not differentiate the function");
1037
  }
1038
  return(differentialNode);
1039
} // End pobyso_differentiate
1040

1041

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

1095
int
1096
pobyso_evaluate_faithful(mpfr_t faithfulEvaluation,
1097
                          node *nodeToEvaluate,
1098
                          mpfr_t argument,
1099
                          mpfr_prec_t precision)
1100
{
1101
  /* Check input arguments. */
1102
  if (nodeToEvaluate == NULL)
1103
  {
1104
    pobyso_error_message("pobyso_evaluate_faithful",
1105
                        "NULL_POINTER_ARGUMENT",
1106
                        "nodeToEvaluate is a NULL pointer");
1107
    return(1);
1108
  }
1109
  evaluateFaithful(faithfulEvaluation,
1110
                   nodeToEvaluate,
1111
                   argument,
1112
                   precision);
1113
  return(0);
1114
} /* End pobyso_evaluate_faithfull. */
1115

1116
chain*
1117
pobyso_find_zeros(node *function,
1118
                  mpfr_t *lower_bound,
1119
                  mpfr_t *upper_bound)
1120
{
1121
  mp_prec_t currentPrecision;
1122
  mpfr_t currentDiameter;
1123
  rangetype bounds;
1124

1125
  currentPrecision = getToolPrecision();
1126
  mpfr_init2(currentDiameter, currentPrecision);
1127

1128
  bounds.a = lower_bound;
1129
  bounds.b = upper_bound;
1130

1131
  if (bounds.a == NULL || bounds.b == NULL)
1132
  {
1133
    pobyso_error_message("pobyso_find_zeros",
1134
                        "MEMORY_ALLOCATION_ERROR",
1135
                        "Could not allocate one of the bounds");
1136
    return(NULL);
1137
  }
1138
  return(findZerosFunction(function,
1139
                            bounds,
1140
                            currentPrecision,
1141
                            currentDiameter));
1142
} /* End pobyso_find_zeros. */
1143

1144
void
1145
pobyso_free_chain_of_nodes(chain *theChainOfNodes)
1146
{
1147
  node *currentNode           = NULL;
1148
  chain *currentChainElement  = NULL;
1149
  chain *nextChainElement     = NULL;
1150

1151
  nextChainElement = theChainOfNodes;
1152

1153
  while(nextChainElement != NULL)
1154
  {
1155
    currentChainElement = nextChainElement;
1156
    currentNode = (node*)(currentChainElement->value);
1157
    nextChainElement = nextChainElement->next;
1158
    free_memory(currentNode);
1159
    free((void*)(currentChainElement));
1160
  }
1161
} /* End pobyso_free_chain_of_nodes. */
1162

1163
void
1164
pobyso_free_range(rangetype range)
1165
{
1166

1167
  mpfr_clear(*(range.a));
1168
  mpfr_clear(*(range.b));
1169
  free(range.a);
1170
  free(range.b);
1171
} /* End pobyso_free_range. */
1172

1173
node*
1174
pobyso_fp_minimax_canonical_monomials_base(node *function,
1175
                                      int degree,
1176
                                      chain *formats,
1177
                                      chain *points,
1178
                                      mpfr_t lowerBound,
1179
                                      mpfr_t upperBound,
1180
                                      int fpFixedArg,
1181
                                      int absRel,
1182
                                      node *constPart,
1183
                                      node *minimax)
1184
{
1185
  return(NULL);
1186
} /* End pobyso_fp_minimax_canonical_monomials_base. */
1187

1188
node*
1189
pobyso_parse_function(char *functionString,
1190
                      char *freeVariableNameString)
1191
{
1192
  if (functionString == NULL || freeVariableNameString == NULL)
1193
  {
1194
    pobyso_error_message("pobyso_parse_function",
1195
                        "NULL_POINTER_ARGUMENT",
1196
                        "One of the arguments is a NULL pointer");
1197
    return(NULL);
1198
  }
1199
  return(parseString(functionString));
1200

1201
} /* End pobyso_parse_function */
1202

1203
node*
1204
pobyso_remez_approx_canonical_monomials_base_for_error(node *functionNode,
1205
                                                  unsigned int mode,
1206
                                                  mpfr_t lowerBound,
1207
                                                  mpfr_t upperBound,
1208
                                                  mpfr_t eps)
1209
{
1210
  node *weight              = NULL;
1211
  node *bestApproxPolyNode  = NULL;
1212
  node *bestApproxHorner    = NULL;
1213
  node *errorNode           = NULL;
1214
  rangetype degreeRange;
1215
  mpfr_t quality;
1216
  mpfr_t currentError;
1217
  unsigned int degree;
1218

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

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

1301
    if (bestApproxPolyNode == NULL)
1302
    {
1303
      pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
1304
                          "INTERNAL_ERROR",
1305
                          "could not compute the bestApproxPolyNode");
1306
      mpfr_clear(currentError);
1307
      mpfr_clear(quality);
1308
      return(NULL);
1309
    }
1310

1311
    setDisplayMode(DISPLAY_MODE_DECIMAL);
1312
    fprintTree(stderr, bestApproxPolyNode);
1313
    fprintf(stderr, "\n\n");
1314

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

1343
node*
1344
pobyso_remez_canonical_monomials_base(node *function,
1345
                                     node *weight,
1346
                                     unsigned int degree,
1347
                                     mpfr_t lowerBound,
1348
                                     mpfr_t upperBound,
1349
                                     mpfr_t quality)
1350
{
1351
  node  *bestApproxPoly = NULL;
1352
  chain *monomials      = NULL;
1353
  chain *curMonomial    = NULL;
1354

1355
  mpfr_t satisfying_error;
1356
  mpfr_t target_error;
1357

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

1402
  while (curMonomial != NULL)
1403
  {
1404
    fprintf(stderr, "monomial tree: ");
1405
    //mpfr_out_str(stderr, 10, 17, *((mpfr_t*)((node*)(curMonomial->value))->value), MPFR_RNDN);
1406
    fprintTree(stderr, (node*)(curMonomial->value));
1407
    fprintf(stderr, "\n");
1408
    curMonomial = curMonomial->next;
1409
  }
1410

1411
  /* Deal with NULL weight. */
1412
  if (weight == NULL)
1413
  {
1414
    weight = makeConstantDouble(1.0);
1415
  }
1416
  /* Compute the best polynomial with the required quality.
1417
     The behavior is as if satisfying error and target_error had
1418
     not been used.*/
1419
  mpfr_init(satisfying_error);
1420
  mpfr_init(target_error);
1421
  mpfr_set_str(satisfying_error, "0", 10, MPFR_RNDN);
1422
  mpfr_set_inf(target_error, 1);
1423

1424

1425
  fprintf(stderr, "satisfying_error: ");
1426
  mpfr_out_str(stderr, 10, 17, satisfying_error, MPFR_RNDN);
1427
  fprintf(stderr, ".\n");
1428
  fprintf(stderr, "target_error: ");
1429
  mpfr_out_str(stderr, 10, 17, target_error,MPFR_RNDN);
1430
  fprintf(stderr, ".\n");
1431

1432
  fprintf(stderr,
1433
          "current precision: %li\n", getToolPrecision());
1434
  /* Call the Sollya function. */
1435
  bestApproxPoly = remez(function,
1436
                          weight,
1437
                          monomials,
1438
                          lowerBound,
1439
                          upperBound,
1440
                          quality,
1441
                          satisfying_error,
1442
                          target_error,
1443
                          getToolPrecision());
1444

1445
  mpfr_clear(satisfying_error);
1446
  mpfr_clear(target_error);
1447
  pobyso_free_chain_of_nodes(monomials);
1448

1449
  return(bestApproxPoly);
1450
} /* End pobyso_remez_canonical_monomials_base. */
1451

1452
#endif
1453

    
1454
void
1455
pobyso_error_message(char *functionName, char *messageName, char* message)
1456
{
1457
  fprintf(stderr, "?%s: %s.\n%s.\n", functionName, messageName, message);
1458
} /* End pobyso_error_message */