Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (27,3 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 expressionSa;
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
      expressionSa = sollya_lib_parse_string(expression);
170
      return expressionSa;
171
    }
172
    else
173
    {
174
      if (expression[i] == ' ' || expression[i] == '\t') /* A blank,
175
                                                           just continue. */
176
      {
177
        continue;
178
      }
179
      else /* a character != ';' and from a blank: create the ';'ed string. */
180
      {
181
        /* Create a new string for the expression, add the ";" and
182
         * and call sollya_lib_parse_string. */
183
        expressionWithSemiCo = calloc(i + 3, sizeof(char));
184
        if (expressionWithSemiCo == NULL)
185
        {
186
          pobyso_error_message("pobyso_parse_string",
187
                                "MEMORY_ALLOCATION_ERROR",
188
                                "Could not allocate the expression string");
189
          return NULL;
190
        }
191
        strncpy(expressionWithSemiCo, expression, i+1);
192
        expressionWithSemiCo[i + 1] = ';';
193
        expressionWithSemiCo[i + 2] = '\0';
194
        expressionSa = sollya_lib_parse_string(expressionWithSemiCo);
195
        free(expressionWithSemiCo);
196
        return expressionSa;
197
      } /* End character != ';' and from a blank. */
198
    /* Create a new string for the expression, add the ";" and
199
     * and call sollya_lib_parse_string. */
200
    } /* End else. */
201
  } /* End for. */
202
  /* We get here, it is because we did not find any char == anything different
203
   * from ' ' or '\t': the string is empty.
204
   */
205
  pobyso_error_message("pobyso_parse_string",
206
                       "ONLY_BLANK_ARGUMENT",
207
                        "The expression is only made of blanks");
208
  return NULL;
209

    
210
} /* pobyso_parse_string */
211

    
212
pobyso_func_exp_t
213
pobyso_remez_canonical_monomials_base(pobyso_func_exp_t function,
214
                                      long int degree,
215
                                      pobyso_range_t interval,
216
                                      pobyso_func_exp_t weight,
217
                                      double quality,
218
                                      pobyso_range_t bounds)
219
{
220
  sollya_obj_t  degreeSo = NULL;
221
  sollya_obj_t qualitySo = NULL;
222

    
223
  degreeSo = sollya_lib_constant_from_int(degree);
224
  qualitySo = sollya_lib_constant_from_double(quality);
225

    
226
  sollya_lib_clear_obj(degreeSo);
227
  sollya_lib_clear_obj(qualitySo);
228
  return NULL;
229
} /* End pobyso_remez_canonical_monomials_base. */
230

    
231
int
232
pobyso_set_canonical_on()
233
{
234
  pobyso_on_off_t currentCanonicalModeSo;
235
  pobyso_on_off_t on;
236

    
237
  currentCanonicalModeSo = sollya_lib_get_canonical();
238
  if (sollya_lib_is_on(currentCanonicalModeSo))
239
  {
240
    sollya_lib_clear_obj(currentCanonicalModeSo);
241
    return POBYSO_ON;
242
  }
243
  else
244
  {
245
    on = sollya_lib_on();
246
    sollya_lib_set_canonical(on);
247
    sollya_lib_clear_obj(on);
248
    sollya_lib_clear_obj(currentCanonicalModeSo);
249
    return POBYSO_OFF;
250
  }
251
} /* End pobyso_set_canonical_on. */
252

    
253
int
254
pobyso_set_verbosity_off()
255
{
256
  sollya_obj_t verbosityLevelZeroSo;
257
  sollya_obj_t currentVerbosityLevelSo = NULL;
258
  int currentVerbosityLevel = 0;
259

    
260
  currentVerbosityLevelSo = sollya_lib_get_verbosity();
261
  sollya_lib_get_constant_as_int(&currentVerbosityLevel,
262
                                 currentVerbosityLevelSo);
263
  verbosityLevelZeroSo = sollya_lib_constant_from_int(0);
264
  sollya_lib_set_verbosity(verbosityLevelZeroSo);
265
  sollya_lib_clear_obj(verbosityLevelZeroSo);
266
  sollya_lib_clear_obj(currentVerbosityLevelSo);
267
  return currentVerbosityLevel;
268
} /* End of pobyso_set_verbosity_off. */
269

    
270
int
271
pobyso_set_verbosity_to(int newVerbosityLevel)
272
{
273
  int initialVerbosityLevel = 0;
274
  sollya_obj_t initialVerbosityLevelSo = NULL;
275
  sollya_obj_t newVerbosityLevelSo = NULL;
276

    
277
  initialVerbosityLevelSo = sollya_lib_get_verbosity();
278
  sollya_lib_get_constant_as_int(&initialVerbosityLevel,
279
                                 initialVerbosityLevelSo);
280
  sollya_lib_clear_obj(initialVerbosityLevelSo);
281
  if (newVerbosityLevel < 0)
282
  {
283
    pobyso_error_message("pobyso_set_verbosity_to",
284
                        "INVALID_VALUE",
285
                        "The new verbosity level is a negative number");
286
    return initialVerbosityLevel;
287
  }
288
  newVerbosityLevelSo = sollya_lib_constant_from_int(newVerbosityLevel);
289
  sollya_lib_set_verbosity(newVerbosityLevelSo);
290
  sollya_lib_clear_obj(newVerbosityLevelSo);
291
  return initialVerbosityLevel;
292
} /* End of pobyso_set_verbosity_to. */
293

    
294
/**
295
 * @see pobyso.h#pobyso_subpoly
296
 */
297
pobyso_func_exp_t
298
pobyso_subpoly(pobyso_func_exp_t polynomialSo, long expsNum,...)
299
{
300
  sollya_obj_t expsListSo = NULL;
301
  sollya_obj_t* expsList  = NULL;
302
  sollya_obj_t subpoly    = NULL;
303

    
304
  va_list vaExpsList;
305
  int currentExp;
306
  int i;
307

    
308
  /* Arguments check. */
309
  if (polynomialSo == NULL) return NULL;
310
  if (expsNum < 0) return NULL;
311
  if (expsNum == 0) return sollya_lib_copy_obj(polynomialSo);
312

    
313
  va_start(vaExpsList, expsNum);
314
  expsList = (sollya_obj_t*) malloc(expsNum * sizeof(sollya_obj_t));
315
  if (expsList == NULL)
316
  {
317
    pobyso_error_message("pobyso_subpoly",
318
                          "MEMORY_ALLOCATION_ERROR",
319
                          "Could not allocate the expression string");
320
    return NULL;
321
  }
322
  for (i = 0 ; i < expsNum ; i++)
323
  {
324
    currentExp = va_arg(vaExpsList, long);
325
    expsList[i] = sollya_lib_constant_from_int64(currentExp);
326
  } /* End for */
327
  va_end(vaExpsList);
328
  expsListSo = sollya_lib_list(expsList, expsNum);
329
  if (expsList == NULL)
330
  {
331
    pobyso_error_message("pobyso_subpoly",
332
                          "LIST_CREATIONERROR",
333
                          "Could not create the exponents list");
334
    for (i = 0 ; i < expsNum ; i++)
335
    {
336
      sollya_lib_clear_obj(expsList[i]);
337
    }
338
    free(expsList);
339
    return NULL;
340
  }
341
  subpoly = sollya_lib_subpoly(polynomialSo, expsListSo);
342
  sollya_lib_clear_obj(expsListSo);
343
  for (i = 0 ; i < expsNum ; i++)
344
  {
345
    sollya_lib_clear_obj(expsList[i]);
346
  }
347
  free(expsList);
348
  return subpoly;
349
} /* pobyso_subpoly. */
350

    
351
/* Attic from the sollya_lib < 4. */
352
#if 0
353
chain*
354
pobyso_create_canonical_monomials_base(const unsigned int degree)
355
{
356
  int i    = 0;
357
  chain *monomials  = NULL;
358
  node  *monomial   = NULL;
359

360
  for(i = degree ; i >= 0  ; i--)
361
  {
362
     monomial   = makePow(makeVariable(), makeConstantDouble((double)i));
363
     monomials  = addElement(monomials, monomial);
364
     fprintf(stderr, "pobyso_create_canonical_monomials_base: %u\n", i);
365
  }
366
  if (monomials == NULL)
367
  {
368
    pobyso_error_message("pobyso_create_canonical_monomial_base",
369
                        "CHAIN_CREATION_ERROR",
370
                        "Could not create the monomials chain");
371
    return(NULL);
372
  }
373
  return(monomials);
374
} /* End pobyso_create_canonical_monomials_base. */
375

376
chain*
377
pobyso_create_chain_from_int_array(int* intArray,
378
                                    const unsigned int arrayLength)
379
{
380
  int i = 0;
381
  chain *newChain = NULL;
382
  int *currentInt;
383

384
  if (arrayLength == 0) return(NULL);
385
  if (intArray == NULL)
386
  {
387
    pobyso_error_message("pobyso_create_chain_from_int_array",
388
                        "NULL_POINTER_ARGUMENT",
389
                        "The array is a NULL pointer");
390
    return(NULL);
391
  }
392
  for (i = arrayLength - 1 ; i >= 0 ; i--)
393
  {
394
    currentInt = malloc(sizeof(int));
395
    if (currentInt == NULL)
396
    {
397
      pobyso_error_message("pobyso_create_chain_from_int_array",
398
                          "MEMORY_ALLOCATION_ERROR",
399
                          "Could not allocate one of the integers");
400
      freeChain(newChain, free);
401
      return(NULL);
402
    }
403
    *currentInt = intArray[i];
404
    newChain = addElement(newChain, currentInt);
405
  }
406
  return(newChain);
407
} // End pobyso_create_chain_from_int_array. */
408

409
chain*
410
pobyso_create_chain_from_unsigned_int_array(unsigned int* intArray,
411
                                        const unsigned int arrayLength)
412
{
413
  int i = 0;
414
  chain *newChain = NULL;
415
  unsigned int *currentInt;
416

417
  /* Argument checking. */
418
  if (arrayLength == 0) return(NULL);
419
  if (intArray == NULL)
420
  {
421
    pobyso_error_message("pobyso_create_chain_from_unsigned_int_array",
422
                        "NULL_POINTER_ARGUMENT",
423
                        "The array is a NULL pointer");
424
    return(NULL);
425
  }
426
  for (i = arrayLength - 1 ; i >= 0 ; i--)
427
  {
428
    currentInt = malloc(sizeof(unsigned int));
429
    if (currentInt == NULL)
430
    {
431
      pobyso_error_message("pobyso_create_chain_from_unsigned_int_array",
432
                          "MEMORY_ALLOCATION_ERROR",
433
                          "Could not allocate one of the integers");
434
      freeChain(newChain, free);
435
      return(NULL);
436
    }
437
    *currentInt = intArray[i];
438
    newChain = addElement(newChain, currentInt);
439
  }
440
  return(newChain);
441
} // End pobyso_create_chain_from_unsigned_int_array. */
442

443
node*
444
pobyso_differentiate(node *functionNode)
445
{
446
  /* Argument checking. */
447
  node *differentialNode;
448
  if (functionNode == NULL)
449
  {
450
    pobyso_error_message("pobyso_differentiate",
451
                        "NULL_POINTER_ARGUMENT",
452
                        "The function to differentiate is a NULL pointer");
453
    return(NULL);
454
  }
455
  differentialNode = differentiate(functionNode);
456
  if (differentialNode == NULL)
457
  {
458
    pobyso_error_message("pobyso_differentiate",
459
                        "INTERNAL ERROR",
460
                        "Sollya could not differentiate the function");
461
  }
462
  return(differentialNode);
463
} // End pobyso_differentiate
464

465

466
int
467
pobyso_dirty_infnorm(mpfr_t infNorm,
468
                      node *functionNode,
469
                      mpfr_t lowerBound,
470
                      mpfr_t upperBound,
471
                      mp_prec_t precision)
472
{
473
  int functionCallResult;
474
  /* Arguments checking. */
475
  if (functionNode == NULL)
476
  {
477
    pobyso_error_message("pobyso_dirty_infnorm",
478
                        "NULL_POINTER_ARGUMENT",
479
                        "The function to compute is a NULL pointer");
480
    return(1);
481
  }
482
  if (mpfr_cmp(lowerBound, upperBound) > 0)
483
  {
484
    pobyso_error_message("pobyso_dirty_infnorm",
485
                        "INCOHERENT_INPUT_DATA",
486
                        "The lower bond is greater than the upper bound");
487
    return(1);
488
  }
489
  /* Particular cases. */
490
  if (mpfr_cmp(lowerBound, upperBound) == 0)
491
  {
492
    functionCallResult = pobyso_evaluate_faithful(infNorm,
493
                                                  functionNode,
494
                                                  lowerBound,
495
                                                  precision);
496
    return(functionCallResult);
497
  }
498
  if (isConstant(functionNode))
499
  {
500
    functionCallResult = pobyso_evaluate_faithful(infNorm,
501
                                                  functionNode,
502
                                                  lowerBound,
503
                                                  precision);
504
    if (!functionCallResult)
505
    {
506
      mpfr_abs(infNorm, infNorm, MPFR_RNDN);
507
    }
508
    return(functionCallResult);
509
  }
510
  uncertifiedInfnorm(infNorm,
511
                      functionNode,
512
                      lowerBound,
513
                      upperBound,
514
                      POBYSO_DEFAULT_POINTS,
515
                      precision);
516
  return(0);
517
} /* End pobyso_dirty_infnorm. */
518

519
int
520
pobyso_evaluate_faithful(mpfr_t faithfulEvaluation,
521
                          node *nodeToEvaluate,
522
                          mpfr_t argument,
523
                          mpfr_prec_t precision)
524
{
525
  /* Check input arguments. */
526
  if (nodeToEvaluate == NULL)
527
  {
528
    pobyso_error_message("pobyso_evaluate_faithful",
529
                        "NULL_POINTER_ARGUMENT",
530
                        "nodeToEvaluate is a NULL pointer");
531
    return(1);
532
  }
533
  evaluateFaithful(faithfulEvaluation,
534
                   nodeToEvaluate,
535
                   argument,
536
                   precision);
537
  return(0);
538
} /* End pobyso_evaluate_faithfull. */
539

540
chain*
541
pobyso_find_zeros(node *function,
542
                  mpfr_t *lower_bound,
543
                  mpfr_t *upper_bound)
544
{
545
  mp_prec_t currentPrecision;
546
  mpfr_t currentDiameter;
547
  rangetype bounds;
548

549
  currentPrecision = getToolPrecision();
550
  mpfr_init2(currentDiameter, currentPrecision);
551

552
  bounds.a = lower_bound;
553
  bounds.b = upper_bound;
554

555
  if (bounds.a == NULL || bounds.b == NULL)
556
  {
557
    pobyso_error_message("pobyso_find_zeros",
558
                        "MEMORY_ALLOCATION_ERROR",
559
                        "Could not allocate one of the bounds");
560
    return(NULL);
561
  }
562
  return(findZerosFunction(function,
563
                            bounds,
564
                            currentPrecision,
565
                            currentDiameter));
566
} /* End pobyso_find_zeros. */
567

568
void
569
pobyso_free_chain_of_nodes(chain *theChainOfNodes)
570
{
571
  node *currentNode           = NULL;
572
  chain *currentChainElement  = NULL;
573
  chain *nextChainElement     = NULL;
574

575
  nextChainElement = theChainOfNodes;
576

577
  while(nextChainElement != NULL)
578
  {
579
    currentChainElement = nextChainElement;
580
    currentNode = (node*)(currentChainElement->value);
581
    nextChainElement = nextChainElement->next;
582
    free_memory(currentNode);
583
    free((void*)(currentChainElement));
584
  }
585
} /* End pobyso_free_chain_of_nodes. */
586

587
void
588
pobyso_free_range(rangetype range)
589
{
590

591
  mpfr_clear(*(range.a));
592
  mpfr_clear(*(range.b));
593
  free(range.a);
594
  free(range.b);
595
} /* End pobyso_free_range. */
596

597
node*
598
pobyso_fp_minimax_canonical_monomials_base(node *function,
599
                                      int degree,
600
                                      chain *formats,
601
                                      chain *points,
602
                                      mpfr_t lowerBound,
603
                                      mpfr_t upperBound,
604
                                      int fpFixedArg,
605
                                      int absRel,
606
                                      node *constPart,
607
                                      node *minimax)
608
{
609
  return(NULL);
610
} /* End pobyso_fp_minimax_canonical_monomials_base. */
611

612
node*
613
pobyso_parse_function(char *functionString,
614
                      char *freeVariableNameString)
615
{
616
  if (functionString == NULL || freeVariableNameString == NULL)
617
  {
618
    pobyso_error_message("pobyso_parse_function",
619
                        "NULL_POINTER_ARGUMENT",
620
                        "One of the arguments is a NULL pointer");
621
    return(NULL);
622
  }
623
  return(parseString(functionString));
624

625
} /* End pobyso_parse_function */
626

627
node*
628
pobyso_remez_approx_canonical_monomials_base_for_error(node *functionNode,
629
                                                  unsigned int mode,
630
                                                  mpfr_t lowerBound,
631
                                                  mpfr_t upperBound,
632
                                                  mpfr_t eps)
633
{
634
  node *weight              = NULL;
635
  node *bestApproxPolyNode  = NULL;
636
  node *bestApproxHorner    = NULL;
637
  node *errorNode           = NULL;
638
  rangetype degreeRange;
639
  mpfr_t quality;
640
  mpfr_t currentError;
641
  unsigned int degree;
642

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

706
  /* Try to refine the initial guess: loop with increasing degrees until
707
   * we find a satisfactory one. */
708
  while(mpfr_cmp(currentError, eps) > 0)
709
  {
710
    /* Get rid of the previous polynomial, if any. */
711
    if (bestApproxPolyNode != NULL)
712
    {
713
      free_memory(bestApproxPolyNode);
714
    }
715
    fprintf(stderr, "Degree: %u\n", degree);
716
    fprintf(stderr, "Calling pobyso_remez_canonical_monomials_base...\n");
717
    /* Try to find a polynomial with the guessed degree. */
718
    bestApproxPolyNode = pobyso_remez_canonical_monomials_base(functionNode,
719
                                                            weight,
720
                                                            degree,
721
                                                            lowerBound,
722
                                                            upperBound,
723
                                                            quality);
724

725
    if (bestApproxPolyNode == NULL)
726
    {
727
      pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
728
                          "INTERNAL_ERROR",
729
                          "could not compute the bestApproxPolyNode");
730
      mpfr_clear(currentError);
731
      mpfr_clear(quality);
732
      return(NULL);
733
    }
734

735
    setDisplayMode(DISPLAY_MODE_DECIMAL);
736
    fprintTree(stderr, bestApproxPolyNode);
737
    fprintf(stderr, "\n\n");
738

739
    errorNode = makeSub(copyTree(functionNode), copyTree(bestApproxPolyNode));
740
    /* Check the error with the computed polynomial. */
741
    uncertifiedInfnorm(currentError,
742
                        errorNode,
743
                        lowerBound,
744
                        upperBound,
745
                        POBYSO_INF_NORM_NUM_POINTS,
746
                        getToolPrecision());
747
    fprintf(stderr, "Inf norm: ");
748
    mpfr_out_str(stderr, 10, 17, currentError, MPFR_RNDN);
749
    fprintf(stderr, "\n\n");
750
    /* Free the errorNode but not the bestApproxPolyNode (we need it if
751
     * we exit the loop at the next iteration). */
752
    free_memory(errorNode);
753
    degree++;
754
  }
755
  /* Use an intermediate variable, since horner() creates a new node
756
   * and does not reorder the argument "in place". This allows for the memory
757
   * reclaim of bestApproxHorner.
758
   */
759
  bestApproxHorner = horner(bestApproxPolyNode);
760
  free_memory(bestApproxPolyNode);
761
  mpfr_clear(currentError);
762
  mpfr_clear(quality);
763
  free_memory(weight);
764
  return(bestApproxHorner);
765
} /* End pobyso_remez_approx_canonical_monomials_base_for_error */
766

767
node*
768
pobyso_remez_canonical_monomials_base(node *function,
769
                                     node *weight,
770
                                     unsigned int degree,
771
                                     mpfr_t lowerBound,
772
                                     mpfr_t upperBound,
773
                                     mpfr_t quality)
774
{
775
  node  *bestApproxPoly = NULL;
776
  chain *monomials      = NULL;
777
  chain *curMonomial    = NULL;
778

779
  mpfr_t satisfying_error;
780
  mpfr_t target_error;
781

782
  /* Argument checking */
783
  /* Function tree. */
784
  if (function == NULL)
785
  {
786
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
787
                        "NULL_POINTER_ARGUMENT",
788
                        "the \"function\" argument is a NULL pointer");
789
    return(NULL);
790
  }
791
  if (weight == NULL)
792
  {
793
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
794
                        "NULL_POINTER_ARGUMENT",
795
                        "the \"weight\" argument is a NULL pointer");
796
    return(NULL);
797
  }
798
  /* Check the bounds. */
799
  if (mpfr_cmp(lowerBound, upperBound) >= 0)
800
  {
801
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
802
                        "INCOHERENT_IMPUT_DATA",
803
                        "the lower_bound >= upper_bound");
804
    return(NULL);
805
  }
806
  /* The quality must be a non null positive number. */
807
  if (mpfr_sgn(quality) <= 0)
808
  {
809
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
810
                        "INCOHERENT_INPUT_DATA",
811
                        "the quality <= 0");
812
  }
813
  /* End argument checking. */
814
  /* Create the monomials nodes chains. */
815
  monomials = pobyso_create_canonical_monomials_base(degree);
816
  fprintf(stderr, "monomials chain length = %d\n", lengthChain(monomials));
817
  if (monomials == NULL || (lengthChain(monomials) != degree + 1))
818
  {
819
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
820
                        "CHAIN_CREATION_ERROR",
821
                        "could not create the monomials chain");
822
    return(NULL);
823
  }
824
  curMonomial = monomials;
825

826
  while (curMonomial != NULL)
827
  {
828
    fprintf(stderr, "monomial tree: ");
829
    //mpfr_out_str(stderr, 10, 17, *((mpfr_t*)((node*)(curMonomial->value))->value), MPFR_RNDN);
830
    fprintTree(stderr, (node*)(curMonomial->value));
831
    fprintf(stderr, "\n");
832
    curMonomial = curMonomial->next;
833
  }
834

835
  /* Deal with NULL weight. */
836
  if (weight == NULL)
837
  {
838
    weight = makeConstantDouble(1.0);
839
  }
840
  /* Compute the best polynomial with the required quality.
841
     The behavior is as if satisfying error and target_error had
842
     not been used.*/
843
  mpfr_init(satisfying_error);
844
  mpfr_init(target_error);
845
  mpfr_set_str(satisfying_error, "0", 10, MPFR_RNDN);
846
  mpfr_set_inf(target_error, 1);
847

848

849
  fprintf(stderr, "satisfying_error: ");
850
  mpfr_out_str(stderr, 10, 17, satisfying_error, MPFR_RNDN);
851
  fprintf(stderr, ".\n");
852
  fprintf(stderr, "target_error: ");
853
  mpfr_out_str(stderr, 10, 17, target_error,MPFR_RNDN);
854
  fprintf(stderr, ".\n");
855

856
  fprintf(stderr,
857
          "current precision: %li\n", getToolPrecision());
858
  /* Call the Sollya function. */
859
  bestApproxPoly = remez(function,
860
                          weight,
861
                          monomials,
862
                          lowerBound,
863
                          upperBound,
864
                          quality,
865
                          satisfying_error,
866
                          target_error,
867
                          getToolPrecision());
868

869
  mpfr_clear(satisfying_error);
870
  mpfr_clear(target_error);
871
  pobyso_free_chain_of_nodes(monomials);
872

873
  return(bestApproxPoly);
874
} /* End pobyso_remez_canonical_monomials_base. */
875

876
#endif
877

    
878
void
879
pobyso_error_message(char *functionName, char *messageName, char* message)
880
{
881
  fprintf(stderr, "?%s: %s.\n%s.\n", functionName, messageName, message);
882
} /* End pobyso_error_message */