Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (27,79 ko)

1
/** @file pobyso.c
2
 * Name & purpose
3
 *
4
 * @author S.T.
5
 * @date 2011-10-12
6
 *
7
 *
8
 */
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 solObj)
38
{
39
  sollya_lib_autoprint(solObj, NULL);
40
} /* End pobyso_autoprint. */
41

    
42
/* @see pobyso.h#pobyso_get_verbosity */
43
int
44
pobyso_get_verbosity()
45
{
46
  sollya_obj_t verbositySo = NULL;
47
  int verbosity            = 0;
48

    
49
  verbositySo = sollya_lib_get_verbosity();
50
  sollya_lib_get_constant_as_int(&verbosity,verbositySo);
51
  sollya_lib_clear_obj(verbositySo);
52
  return verbosity;
53
} /* End pobyso_get_verbosity. */
54

    
55
/* @see pobyso.h#pobyso_is_constant_expression*/
56
int
57
pobyso_is_constant_expression(sollya_obj_t obj_to_test)
58
{
59
  mpfr_t dummy;
60
  int test;
61
  int initial_verbosity_level      = 0;
62

    
63
  /* Test argument. */
64
  if (obj_to_test == NULL)
65
  {
66
    pobyso_error_message("pobyso_parse_string",
67
                        "NULL_POINTER_ARGUMENT",
68
                        "The expression is a NULL pointer");
69
    return 0;
70
  }
71
  initial_verbosity_level = pobyso_set_verbosity_off();
72

    
73
  if (! sollya_lib_obj_is_function(obj_to_test))
74
  {
75
    pobyso_set_verbosity_to(initial_verbosity_level);
76
    return 0;
77
  }
78
  mpfr_init2(dummy,64);
79
  /* Call to previous Sollya function resets verbosity. */
80
  pobyso_set_verbosity_off();
81
  test = sollya_lib_get_constant(dummy, obj_to_test);
82
  mpfr_clear(dummy);
83
  pobyso_set_verbosity_to(initial_verbosity_level);
84
  return test;
85
} /* End pobyso_is_constant_expression. */
86

    
87
/** @see pobyso.h#pobyso_new_monomial. */
88
pobyso_func_exp_t
89
pobyso_new_monomial(pobyso_func_exp_t coefficientSo, long degree)
90
{
91
  sollya_obj_t degreeSo   = NULL;
92
  sollya_obj_t varToPowSo = NULL;
93
  sollya_obj_t monomialSo = NULL;
94
  int initial_verbosity_level = 0;
95

    
96
  /* Arguments check. */
97
  if (coefficientSo == NULL)
98
  {
99
    pobyso_error_message("pobyso_parse_string",
100
                        "NULL_POINTER_ARGUMENT",
101
                        "The expression is a NULL pointer");
102
    return NULL;
103
  }
104
  if (! pobyso_is_constant_expression(coefficientSo))
105
  {
106
    return NULL;
107
  }
108
  if (degree < 0)
109
  {
110
    pobyso_error_message("pobyso_new_monomial",
111
                        "NEGATIVE_DEGREE_ARGUMENT",
112
                        "The degree is a negative integer");
113
    return NULL;
114
  }
115
  /* If degree == 0, just return a copy of the coefficient. Do not
116
   * return the coefficient itself to avoid "double clear" issues. */
117
  if (degree == 0)
118
  {
119
    initial_verbosity_level = pobyso_set_verbosity_off();
120
    monomialSo = sollya_lib_copy_obj(coefficientSo);
121
    pobyso_set_verbosity_to(initial_verbosity_level);
122
  }
123
  degreeSo    = sollya_lib_constant_from_int64(degree);
124
  varToPowSo  = sollya_lib_build_function_pow(sollya_lib_free_variable(),
125
                                              degreeSo);
126
  /* Do not use the "build" version to avoid "eating up" the coefficient. */
127
  monomialSo = sollya_lib_mul(coefficientSo,varToPowSo);
128
  sollya_lib_clear_obj(varToPowSo);
129
  /* Do not clear degreeSa: it was "eaten" by sollya-lib_build_function. */
130
  return monomialSo;
131
} /* End pobyso_new_monomial. */
132

    
133
/* @see pobyso.h#pobyso_parse_string*/
134
pobyso_func_exp_t
135
pobyso_parse_string(const char* expression)
136
{
137
  int expressionLength, i;
138
  char *expressionWithSemiCo;
139
  sollya_obj_t expressionSo;
140

    
141
  /* Arguments check. */
142
  if (expression == NULL)
143
  {
144
    pobyso_error_message("pobyso_parse_string",
145
                        "NULL_POINTER_ARGUMENT",
146
                        "The expression is a NULL pointer");
147
    return  NULL;
148
  }
149
  expressionLength = strlen(expression);
150
  if (expressionLength == 0)
151
  {
152
    pobyso_error_message("pobyso_parse_string",
153
                        "EMPTY_STRING_ARGUMENT",
154
                        "The expression is an empty string");
155
    return NULL;
156
  }
157
  /* Search from the last char of the expression until, whichever happens
158
   * first:
159
   * a ";" is found;
160
   * a char  != ';' is found the the ";" is appended.
161
   * If the head of the string is reached before any of these two events happens
162
   * return an error.
163
   */
164
  for (i = expressionLength - 1 ; i >= 0 ; i--)
165
  {
166
    if (expression[i] == ';') /* Nothing special to do:
167
                                 try to parse the string*/
168
    {
169
      expressionSo = sollya_lib_parse_string(expression);
170
      if (sollya_lib_obj_is_error(expressionSo))
171
      {
172
        sollya_lib_clear_obj(expressionSo);
173
        return NULL;
174
      }
175
      else
176
      {
177
        return expressionSo;
178
      }
179
    }
180
    else
181
    {
182
      if (expression[i] == ' ' || expression[i] == '\t') /* A blank,
183
                                                           just continue. */
184
      {
185
        continue;
186
      }
187
      else /* a character != ';' and from a blank: create the ';'ed string. */
188
      {
189
        /* Create a new string for the expression, add the ";" and
190
         * and call sollya_lib_parse_string. */
191
        expressionWithSemiCo = calloc(i + 3, sizeof(char));
192
        if (expressionWithSemiCo == NULL)
193
        {
194
          pobyso_error_message("pobyso_parse_string",
195
                                "MEMORY_ALLOCATION_ERROR",
196
                                "Could not allocate the expression string");
197
          return NULL;
198
        }
199
        strncpy(expressionWithSemiCo, expression, i+1);
200
        expressionWithSemiCo[i + 1] = ';';
201
        expressionWithSemiCo[i + 2] = '\0';
202
        expressionSo = sollya_lib_parse_string(expressionWithSemiCo);
203
        free(expressionWithSemiCo);
204
        if (sollya_lib_obj_is_error(expressionSo))
205
        {
206
          sollya_lib_clear_obj(expressionSo);
207
          return NULL;
208
        }
209
        else
210
        {
211
          return expressionSo;
212
        }
213
      } /* End character != ';' and from a blank. */
214
    /* Create a new string for the expression, add the ";" and
215
     * and call sollya_lib_parse_string. */
216
    } /* End else. */
217
  } /* End for. */
218
  /* We get here, it is because we did not find any char == anything different
219
   * from ' ' or '\t': the string is empty.
220
   */
221
  pobyso_error_message("pobyso_parse_string",
222
                       "ONLY_BLANK_ARGUMENT",
223
                        "The expression is only made of blanks");
224
  return NULL;
225
} /* pobyso_parse_string */
226

    
227
pobyso_func_exp_t
228
pobyso_remez_canonical_monomials_base(pobyso_func_exp_t function,
229
                                      long int degree,
230
                                      pobyso_range_t interval,
231
                                      pobyso_func_exp_t weight,
232
                                      double quality,
233
                                      pobyso_range_t bounds)
234
{
235
  sollya_obj_t  degreeSo = NULL;
236
  sollya_obj_t qualitySo = NULL;
237

    
238
  degreeSo = sollya_lib_constant_from_int(degree);
239
  qualitySo = sollya_lib_constant_from_double(quality);
240

    
241
  sollya_lib_clear_obj(degreeSo);
242
  sollya_lib_clear_obj(qualitySo);
243
  return NULL;
244
} /* End pobyso_remez_canonical_monomials_base. */
245

    
246
int
247
pobyso_set_canonical_on()
248
{
249
  pobyso_on_off_t currentCanonicalModeSo;
250
  pobyso_on_off_t on;
251

    
252
  currentCanonicalModeSo = sollya_lib_get_canonical();
253
  if (sollya_lib_is_on(currentCanonicalModeSo))
254
  {
255
    sollya_lib_clear_obj(currentCanonicalModeSo);
256
    return POBYSO_ON;
257
  }
258
  else
259
  {
260
    on = sollya_lib_on();
261
    sollya_lib_set_canonical(on);
262
    sollya_lib_clear_obj(on);
263
    sollya_lib_clear_obj(currentCanonicalModeSo);
264
    return POBYSO_OFF;
265
  }
266
} /* End pobyso_set_canonical_on. */
267

    
268
int
269
pobyso_set_verbosity_off()
270
{
271
  sollya_obj_t verbosityLevelZeroSo;
272
  sollya_obj_t currentVerbosityLevelSo = NULL;
273
  int currentVerbosityLevel = 0;
274

    
275
  currentVerbosityLevelSo = sollya_lib_get_verbosity();
276
  sollya_lib_get_constant_as_int(&currentVerbosityLevel,
277
                                 currentVerbosityLevelSo);
278
  verbosityLevelZeroSo = sollya_lib_constant_from_int(0);
279
  sollya_lib_set_verbosity(verbosityLevelZeroSo);
280
  sollya_lib_clear_obj(verbosityLevelZeroSo);
281
  sollya_lib_clear_obj(currentVerbosityLevelSo);
282
  return currentVerbosityLevel;
283
} /* End of pobyso_set_verbosity_off. */
284

    
285
int
286
pobyso_set_verbosity_to(int newVerbosityLevel)
287
{
288
  int initialVerbosityLevel = 0;
289
  sollya_obj_t initialVerbosityLevelSo = NULL;
290
  sollya_obj_t newVerbosityLevelSo = NULL;
291

    
292
  initialVerbosityLevelSo = sollya_lib_get_verbosity();
293
  sollya_lib_get_constant_as_int(&initialVerbosityLevel,
294
                                 initialVerbosityLevelSo);
295
  sollya_lib_clear_obj(initialVerbosityLevelSo);
296
  if (newVerbosityLevel < 0)
297
  {
298
    pobyso_error_message("pobyso_set_verbosity_to",
299
                        "INVALID_VALUE",
300
                        "The new verbosity level is a negative number");
301
    return initialVerbosityLevel;
302
  }
303
  newVerbosityLevelSo = sollya_lib_constant_from_int(newVerbosityLevel);
304
  sollya_lib_set_verbosity(newVerbosityLevelSo);
305
  sollya_lib_clear_obj(newVerbosityLevelSo);
306
  return initialVerbosityLevel;
307
} /* End of pobyso_set_verbosity_to. */
308

    
309
/**
310
 * @see pobyso.h#pobyso_subpoly
311
 */
312
pobyso_func_exp_t
313
pobyso_subpoly(pobyso_func_exp_t polynomialSo, long expsNum, long int* expsList)
314
{
315
  sollya_obj_t  expsListSo    = NULL;
316
  sollya_obj_t* expsList_pso  = NULL;
317
  sollya_obj_t subpoly        = NULL;
318
  int i, j;
319

    
320
  /* Arguments check. */
321
  if (polynomialSo == NULL) return NULL;
322
  if (expsNum < 0) return NULL;
323
  if (expsNum == 0) return sollya_lib_copy_obj(polynomialSo);
324
  if (expsList == 0) return NULL;
325
  /* Create a list of Sollya constants. */
326
  expsList_pso = (sollya_obj_t*) malloc(expsNum * sizeof(sollya_obj_t));
327
  if (expsList_pso == NULL)
328
  {
329
    pobyso_error_message("pobyso_subpoly",
330
                          "MEMORY_ALLOCATION_ERROR",
331
                          "Could not allocate the Sollya exponents list");
332
    return NULL;
333
  }
334
  /* Fill up the list. */
335
  for (i = 0 ; i < expsNum ; i++)
336
  {
337
    /* Abort if an exponent is negative. */
338
    if (expsList[i] < 0 )
339
    {
340
      for (j = 0 ; j < i ; j++)
341
      {
342
        sollya_lib_clear_obj(expsList_pso[j]);
343
      }
344
      free(expsList_pso);
345
      return NULL;
346
    }
347
    expsList_pso[i] = sollya_lib_constant_from_int64(expsList[i]);
348
  } /* End for */
349
  expsListSo = sollya_lib_list(expsList_pso, expsNum);
350
  for (i = 0 ; i < expsNum ; i++)
351
  {
352
    sollya_lib_clear_obj(expsList_pso[i]);
353
  }
354
  free(expsList_pso);
355
  if (expsListSo == NULL)
356
  {
357
    pobyso_error_message("pobyso_subpoly",
358
                          "LIST_CREATIONERROR",
359
                          "Could not create the exponents list");
360
    return NULL;
361
  }
362
  subpoly = sollya_lib_subpoly(polynomialSo, expsListSo);
363
  pobyso_autoprint(expsListSo);
364
  sollya_lib_clear_obj(expsListSo);
365
  return subpoly;
366
} /* pobyso_subpoly. */
367

    
368
/* Attic from the sollya_lib < 4. */
369
#if 0
370
chain*
371
pobyso_create_canonical_monomials_base(const unsigned int degree)
372
{
373
  int i    = 0;
374
  chain *monomials  = NULL;
375
  node  *monomial   = NULL;
376

377
  for(i = degree ; i >= 0  ; i--)
378
  {
379
     monomial   = makePow(makeVariable(), makeConstantDouble((double)i));
380
     monomials  = addElement(monomials, monomial);
381
     fprintf(stderr, "pobyso_create_canonical_monomials_base: %u\n", i);
382
  }
383
  if (monomials == NULL)
384
  {
385
    pobyso_error_message("pobyso_create_canonical_monomial_base",
386
                        "CHAIN_CREATION_ERROR",
387
                        "Could not create the monomials chain");
388
    return(NULL);
389
  }
390
  return(monomials);
391
} /* End pobyso_create_canonical_monomials_base. */
392

393
chain*
394
pobyso_create_chain_from_int_array(int* intArray,
395
                                    const unsigned int arrayLength)
396
{
397
  int i = 0;
398
  chain *newChain = NULL;
399
  int *currentInt;
400

401
  if (arrayLength == 0) return(NULL);
402
  if (intArray == NULL)
403
  {
404
    pobyso_error_message("pobyso_create_chain_from_int_array",
405
                        "NULL_POINTER_ARGUMENT",
406
                        "The array is a NULL pointer");
407
    return(NULL);
408
  }
409
  for (i = arrayLength - 1 ; i >= 0 ; i--)
410
  {
411
    currentInt = malloc(sizeof(int));
412
    if (currentInt == NULL)
413
    {
414
      pobyso_error_message("pobyso_create_chain_from_int_array",
415
                          "MEMORY_ALLOCATION_ERROR",
416
                          "Could not allocate one of the integers");
417
      freeChain(newChain, free);
418
      return(NULL);
419
    }
420
    *currentInt = intArray[i];
421
    newChain = addElement(newChain, currentInt);
422
  }
423
  return(newChain);
424
} // End pobyso_create_chain_from_int_array. */
425

426
chain*
427
pobyso_create_chain_from_unsigned_int_array(unsigned int* intArray,
428
                                        const unsigned int arrayLength)
429
{
430
  int i = 0;
431
  chain *newChain = NULL;
432
  unsigned int *currentInt;
433

434
  /* Argument checking. */
435
  if (arrayLength == 0) return(NULL);
436
  if (intArray == NULL)
437
  {
438
    pobyso_error_message("pobyso_create_chain_from_unsigned_int_array",
439
                        "NULL_POINTER_ARGUMENT",
440
                        "The array is a NULL pointer");
441
    return(NULL);
442
  }
443
  for (i = arrayLength - 1 ; i >= 0 ; i--)
444
  {
445
    currentInt = malloc(sizeof(unsigned int));
446
    if (currentInt == NULL)
447
    {
448
      pobyso_error_message("pobyso_create_chain_from_unsigned_int_array",
449
                          "MEMORY_ALLOCATION_ERROR",
450
                          "Could not allocate one of the integers");
451
      freeChain(newChain, free);
452
      return(NULL);
453
    }
454
    *currentInt = intArray[i];
455
    newChain = addElement(newChain, currentInt);
456
  }
457
  return(newChain);
458
} // End pobyso_create_chain_from_unsigned_int_array. */
459

460
node*
461
pobyso_differentiate(node *functionNode)
462
{
463
  /* Argument checking. */
464
  node *differentialNode;
465
  if (functionNode == NULL)
466
  {
467
    pobyso_error_message("pobyso_differentiate",
468
                        "NULL_POINTER_ARGUMENT",
469
                        "The function to differentiate is a NULL pointer");
470
    return(NULL);
471
  }
472
  differentialNode = differentiate(functionNode);
473
  if (differentialNode == NULL)
474
  {
475
    pobyso_error_message("pobyso_differentiate",
476
                        "INTERNAL ERROR",
477
                        "Sollya could not differentiate the function");
478
  }
479
  return(differentialNode);
480
} // End pobyso_differentiate
481

482

483
int
484
pobyso_dirty_infnorm(mpfr_t infNorm,
485
                      node *functionNode,
486
                      mpfr_t lowerBound,
487
                      mpfr_t upperBound,
488
                      mp_prec_t precision)
489
{
490
  int functionCallResult;
491
  /* Arguments checking. */
492
  if (functionNode == NULL)
493
  {
494
    pobyso_error_message("pobyso_dirty_infnorm",
495
                        "NULL_POINTER_ARGUMENT",
496
                        "The function to compute is a NULL pointer");
497
    return(1);
498
  }
499
  if (mpfr_cmp(lowerBound, upperBound) > 0)
500
  {
501
    pobyso_error_message("pobyso_dirty_infnorm",
502
                        "INCOHERENT_INPUT_DATA",
503
                        "The lower bond is greater than the upper bound");
504
    return(1);
505
  }
506
  /* Particular cases. */
507
  if (mpfr_cmp(lowerBound, upperBound) == 0)
508
  {
509
    functionCallResult = pobyso_evaluate_faithful(infNorm,
510
                                                  functionNode,
511
                                                  lowerBound,
512
                                                  precision);
513
    return(functionCallResult);
514
  }
515
  if (isConstant(functionNode))
516
  {
517
    functionCallResult = pobyso_evaluate_faithful(infNorm,
518
                                                  functionNode,
519
                                                  lowerBound,
520
                                                  precision);
521
    if (!functionCallResult)
522
    {
523
      mpfr_abs(infNorm, infNorm, MPFR_RNDN);
524
    }
525
    return(functionCallResult);
526
  }
527
  uncertifiedInfnorm(infNorm,
528
                      functionNode,
529
                      lowerBound,
530
                      upperBound,
531
                      POBYSO_DEFAULT_POINTS,
532
                      precision);
533
  return(0);
534
} /* End pobyso_dirty_infnorm. */
535

536
int
537
pobyso_evaluate_faithful(mpfr_t faithfulEvaluation,
538
                          node *nodeToEvaluate,
539
                          mpfr_t argument,
540
                          mpfr_prec_t precision)
541
{
542
  /* Check input arguments. */
543
  if (nodeToEvaluate == NULL)
544
  {
545
    pobyso_error_message("pobyso_evaluate_faithful",
546
                        "NULL_POINTER_ARGUMENT",
547
                        "nodeToEvaluate is a NULL pointer");
548
    return(1);
549
  }
550
  evaluateFaithful(faithfulEvaluation,
551
                   nodeToEvaluate,
552
                   argument,
553
                   precision);
554
  return(0);
555
} /* End pobyso_evaluate_faithfull. */
556

557
chain*
558
pobyso_find_zeros(node *function,
559
                  mpfr_t *lower_bound,
560
                  mpfr_t *upper_bound)
561
{
562
  mp_prec_t currentPrecision;
563
  mpfr_t currentDiameter;
564
  rangetype bounds;
565

566
  currentPrecision = getToolPrecision();
567
  mpfr_init2(currentDiameter, currentPrecision);
568

569
  bounds.a = lower_bound;
570
  bounds.b = upper_bound;
571

572
  if (bounds.a == NULL || bounds.b == NULL)
573
  {
574
    pobyso_error_message("pobyso_find_zeros",
575
                        "MEMORY_ALLOCATION_ERROR",
576
                        "Could not allocate one of the bounds");
577
    return(NULL);
578
  }
579
  return(findZerosFunction(function,
580
                            bounds,
581
                            currentPrecision,
582
                            currentDiameter));
583
} /* End pobyso_find_zeros. */
584

585
void
586
pobyso_free_chain_of_nodes(chain *theChainOfNodes)
587
{
588
  node *currentNode           = NULL;
589
  chain *currentChainElement  = NULL;
590
  chain *nextChainElement     = NULL;
591

592
  nextChainElement = theChainOfNodes;
593

594
  while(nextChainElement != NULL)
595
  {
596
    currentChainElement = nextChainElement;
597
    currentNode = (node*)(currentChainElement->value);
598
    nextChainElement = nextChainElement->next;
599
    free_memory(currentNode);
600
    free((void*)(currentChainElement));
601
  }
602
} /* End pobyso_free_chain_of_nodes. */
603

604
void
605
pobyso_free_range(rangetype range)
606
{
607

608
  mpfr_clear(*(range.a));
609
  mpfr_clear(*(range.b));
610
  free(range.a);
611
  free(range.b);
612
} /* End pobyso_free_range. */
613

614
node*
615
pobyso_fp_minimax_canonical_monomials_base(node *function,
616
                                      int degree,
617
                                      chain *formats,
618
                                      chain *points,
619
                                      mpfr_t lowerBound,
620
                                      mpfr_t upperBound,
621
                                      int fpFixedArg,
622
                                      int absRel,
623
                                      node *constPart,
624
                                      node *minimax)
625
{
626
  return(NULL);
627
} /* End pobyso_fp_minimax_canonical_monomials_base. */
628

629
node*
630
pobyso_parse_function(char *functionString,
631
                      char *freeVariableNameString)
632
{
633
  if (functionString == NULL || freeVariableNameString == NULL)
634
  {
635
    pobyso_error_message("pobyso_parse_function",
636
                        "NULL_POINTER_ARGUMENT",
637
                        "One of the arguments is a NULL pointer");
638
    return(NULL);
639
  }
640
  return(parseString(functionString));
641

642
} /* End pobyso_parse_function */
643

644
node*
645
pobyso_remez_approx_canonical_monomials_base_for_error(node *functionNode,
646
                                                  unsigned int mode,
647
                                                  mpfr_t lowerBound,
648
                                                  mpfr_t upperBound,
649
                                                  mpfr_t eps)
650
{
651
  node *weight              = NULL;
652
  node *bestApproxPolyNode  = NULL;
653
  node *bestApproxHorner    = NULL;
654
  node *errorNode           = NULL;
655
  rangetype degreeRange;
656
  mpfr_t quality;
657
  mpfr_t currentError;
658
  unsigned int degree;
659

660
  /* Check the parameters. */
661
  if (functionNode == NULL)
662
  {
663
    pobyso_error_message("remezApproxCanonicalMonomialsBaseForError",
664
                        "NULL_POINTER_ARGUMENT",
665
                        "functionNode is a NULL pointer");
666
    return(NULL);
667
  }
668
  if (mpfr_cmp(lowerBound, upperBound) >= 0)
669
  {
670
    pobyso_error_message("remezApproxCanonicalMonomialsBaseForError",
671
                        "INCOHERENT_INPUT_DATA",
672
                        "the lower_bound >= upper_bound");
673
    return(NULL);
674
  }
675
  /* Set the weight. */
676
  if (mode == POBYSO_ABSOLUTE)
677
  {
678
    /* Set the weight to 1 for the ABSOLUTE_MODE. */
679
    weight = makeConstantDouble(1.0);
680
  }
681
  else
682
  {
683
    if (mode == POBYSO_RELATIVE)
684
    {
685
      pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
686
                          "NOT_IMPLEMENTED",
687
                          "the search for relative error is not implemented yet");
688
      return(NULL);
689
    }
690
    else
691
    {
692
      pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
693
                          "INCOHERENT_INPUT_DATA",
694
                          "the mode is node of POBYSO_ABOLUTE or POBYSO_RELATIVE");
695
      return(NULL);
696
    }
697
  }
698
  //fprintf(stderr, "\n\n\n******* I'm here! ********\n\n\n");
699
  degreeRange = guessDegree(functionNode,
700
                            weight,
701
                            lowerBound,
702
                            upperBound,
703
                            eps,
704
                            POBYSO_GUESS_DEGREE_BOUND);
705
  degree = mpfr_get_ui(*(degreeRange.a), MPFR_RNDN);
706
  //fprintf(stderr, "\n\n\n******* I'm back! ********\n\n\n");
707
  fprintf(stderr, "Guessed degree: ");
708
  mpfr_out_str(stderr, 10, 17, *(degreeRange.a), MPFR_RNDN);
709
  fprintf(stderr, " - as int: %u\n", degree);
710
  /* Reduce the degree by 1 in the foolish hope it could work. */
711
  if (degree > 0) degree--;
712
  /* Both elements of degreeRange where "inited" within guessDegree. */
713
  mpfr_clear(*(degreeRange.a));
714
  mpfr_clear(*(degreeRange.b));
715
  free(degreeRange.a);
716
  free(degreeRange.b);
717
  /* Mimic the default behavior of interactive Sollya. */
718
  mpfr_init(quality);
719
  mpfr_set_d(quality, 1e-5, MPFR_RNDN);
720
  mpfr_init2(currentError, getToolPrecision());
721
  mpfr_set_inf(currentError,1);
722

723
  /* Try to refine the initial guess: loop with increasing degrees until
724
   * we find a satisfactory one. */
725
  while(mpfr_cmp(currentError, eps) > 0)
726
  {
727
    /* Get rid of the previous polynomial, if any. */
728
    if (bestApproxPolyNode != NULL)
729
    {
730
      free_memory(bestApproxPolyNode);
731
    }
732
    fprintf(stderr, "Degree: %u\n", degree);
733
    fprintf(stderr, "Calling pobyso_remez_canonical_monomials_base...\n");
734
    /* Try to find a polynomial with the guessed degree. */
735
    bestApproxPolyNode = pobyso_remez_canonical_monomials_base(functionNode,
736
                                                            weight,
737
                                                            degree,
738
                                                            lowerBound,
739
                                                            upperBound,
740
                                                            quality);
741

742
    if (bestApproxPolyNode == NULL)
743
    {
744
      pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
745
                          "INTERNAL_ERROR",
746
                          "could not compute the bestApproxPolyNode");
747
      mpfr_clear(currentError);
748
      mpfr_clear(quality);
749
      return(NULL);
750
    }
751

752
    setDisplayMode(DISPLAY_MODE_DECIMAL);
753
    fprintTree(stderr, bestApproxPolyNode);
754
    fprintf(stderr, "\n\n");
755

756
    errorNode = makeSub(copyTree(functionNode), copyTree(bestApproxPolyNode));
757
    /* Check the error with the computed polynomial. */
758
    uncertifiedInfnorm(currentError,
759
                        errorNode,
760
                        lowerBound,
761
                        upperBound,
762
                        POBYSO_INF_NORM_NUM_POINTS,
763
                        getToolPrecision());
764
    fprintf(stderr, "Inf norm: ");
765
    mpfr_out_str(stderr, 10, 17, currentError, MPFR_RNDN);
766
    fprintf(stderr, "\n\n");
767
    /* Free the errorNode but not the bestApproxPolyNode (we need it if
768
     * we exit the loop at the next iteration). */
769
    free_memory(errorNode);
770
    degree++;
771
  }
772
  /* Use an intermediate variable, since horner() creates a new node
773
   * and does not reorder the argument "in place". This allows for the memory
774
   * reclaim of bestApproxHorner.
775
   */
776
  bestApproxHorner = horner(bestApproxPolyNode);
777
  free_memory(bestApproxPolyNode);
778
  mpfr_clear(currentError);
779
  mpfr_clear(quality);
780
  free_memory(weight);
781
  return(bestApproxHorner);
782
} /* End pobyso_remez_approx_canonical_monomials_base_for_error */
783

784
node*
785
pobyso_remez_canonical_monomials_base(node *function,
786
                                     node *weight,
787
                                     unsigned int degree,
788
                                     mpfr_t lowerBound,
789
                                     mpfr_t upperBound,
790
                                     mpfr_t quality)
791
{
792
  node  *bestApproxPoly = NULL;
793
  chain *monomials      = NULL;
794
  chain *curMonomial    = NULL;
795

796
  mpfr_t satisfying_error;
797
  mpfr_t target_error;
798

799
  /* Argument checking */
800
  /* Function tree. */
801
  if (function == NULL)
802
  {
803
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
804
                        "NULL_POINTER_ARGUMENT",
805
                        "the \"function\" argument is a NULL pointer");
806
    return(NULL);
807
  }
808
  if (weight == NULL)
809
  {
810
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
811
                        "NULL_POINTER_ARGUMENT",
812
                        "the \"weight\" argument is a NULL pointer");
813
    return(NULL);
814
  }
815
  /* Check the bounds. */
816
  if (mpfr_cmp(lowerBound, upperBound) >= 0)
817
  {
818
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
819
                        "INCOHERENT_IMPUT_DATA",
820
                        "the lower_bound >= upper_bound");
821
    return(NULL);
822
  }
823
  /* The quality must be a non null positive number. */
824
  if (mpfr_sgn(quality) <= 0)
825
  {
826
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
827
                        "INCOHERENT_INPUT_DATA",
828
                        "the quality <= 0");
829
  }
830
  /* End argument checking. */
831
  /* Create the monomials nodes chains. */
832
  monomials = pobyso_create_canonical_monomials_base(degree);
833
  fprintf(stderr, "monomials chain length = %d\n", lengthChain(monomials));
834
  if (monomials == NULL || (lengthChain(monomials) != degree + 1))
835
  {
836
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
837
                        "CHAIN_CREATION_ERROR",
838
                        "could not create the monomials chain");
839
    return(NULL);
840
  }
841
  curMonomial = monomials;
842

843
  while (curMonomial != NULL)
844
  {
845
    fprintf(stderr, "monomial tree: ");
846
    //mpfr_out_str(stderr, 10, 17, *((mpfr_t*)((node*)(curMonomial->value))->value), MPFR_RNDN);
847
    fprintTree(stderr, (node*)(curMonomial->value));
848
    fprintf(stderr, "\n");
849
    curMonomial = curMonomial->next;
850
  }
851

852
  /* Deal with NULL weight. */
853
  if (weight == NULL)
854
  {
855
    weight = makeConstantDouble(1.0);
856
  }
857
  /* Compute the best polynomial with the required quality.
858
     The behavior is as if satisfying error and target_error had
859
     not been used.*/
860
  mpfr_init(satisfying_error);
861
  mpfr_init(target_error);
862
  mpfr_set_str(satisfying_error, "0", 10, MPFR_RNDN);
863
  mpfr_set_inf(target_error, 1);
864

865

866
  fprintf(stderr, "satisfying_error: ");
867
  mpfr_out_str(stderr, 10, 17, satisfying_error, MPFR_RNDN);
868
  fprintf(stderr, ".\n");
869
  fprintf(stderr, "target_error: ");
870
  mpfr_out_str(stderr, 10, 17, target_error,MPFR_RNDN);
871
  fprintf(stderr, ".\n");
872

873
  fprintf(stderr,
874
          "current precision: %li\n", getToolPrecision());
875
  /* Call the Sollya function. */
876
  bestApproxPoly = remez(function,
877
                          weight,
878
                          monomials,
879
                          lowerBound,
880
                          upperBound,
881
                          quality,
882
                          satisfying_error,
883
                          target_error,
884
                          getToolPrecision());
885

886
  mpfr_clear(satisfying_error);
887
  mpfr_clear(target_error);
888
  pobyso_free_chain_of_nodes(monomials);
889

890
  return(bestApproxPoly);
891
} /* End pobyso_remez_canonical_monomials_base. */
892

893
#endif
894

    
895
void
896
pobyso_error_message(char *functionName, char *messageName, char* message)
897
{
898
  fprintf(stderr, "?%s: %s.\n%s.\n", functionName, messageName, message);
899
} /* End pobyso_error_message */