Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (31,75 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_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
 * Strategy: rely on sollya_lib_get_constant. It return 1, when the
57
 * expression is constant.
58
 */
59
int
60
pobyso_is_constant_expression(sollya_obj_t obj_to_test)
61
{
62
  mpfr_t dummy;
63
  int test;
64
  int initial_verbosity_level      = 0;
65

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

    
76
  if (! sollya_lib_obj_is_function(obj_to_test))
77
  {
78
    pobyso_set_verbosity_to(initial_verbosity_level);
79
    return 0;
80
  }
81
  mpfr_init2(dummy,64);
82
  /* Call to previous Sollya function resets verbosity. */
83
  /* Todo: change verbosity suppression strategy with a message call back. */
84
  pobyso_set_verbosity_off();
85
  test = sollya_lib_get_constant(dummy, obj_to_test);
86
  mpfr_clear(dummy);
87
  pobyso_set_verbosity_to(initial_verbosity_level);
88
  return test;
89
} /* End pobyso_is_constant_expression. */
90

    
91
/** @see pobyso.h#pobyso_is_free_var_int_poson_power. */
92
int
93
pobyso_is_free_var_posze_int_power(sollya_obj_t objToTestSo)
94
{
95
  int arity;
96
  sollya_base_function_t headTypeSo;
97
  sollya_obj_t sub1So           = NULL;
98
  sollya_obj_t sub2So           = NULL;
99

    
100
  /* Argument check. */
101
  if (objToTestSo == NULL)
102
  {
103
    pobyso_error_message("pobyso_is_free_var_int_poson_power",
104
                        "NULL_POINTER_ARGUMENT",
105
                        "The expression is a NULL pointer");
106
    return 0;
107
  }
108
  if (! sollya_lib_obj_is_function(objToTestSo))
109
  {
110
    return 0;
111
  }
112
  if (!sollya_lib_get_head_function(&headTypeSo, objToTestSo)) return 0;
113
  if (! sollya_lib_get_subfunctions(objToTestSo,
114
                                    &arity,
115
                                    &sub1So,
116
                                    &sub2So,
117
                                    NULL)) return 0;
118
  /* Power function: arity == 2. */
119
  if (arity != 2) return 0;
120
  if (! pobyso_is_constant_expression(sub1So)) return 0;
121
  return 1;
122
} /* End pobyso_is_free_var_posze_int_power. */
123

    
124

    
125
/** @see pobyso.h#pobyso_is_monomial. */
126
int
127
pobyso_is_int(pobyso_func_exp_t exprSo)
128
{
129
  mpfr_t float1M;
130
  mpfr_t float2M;
131
  mpfr_t tempFloat1M;
132
  mpfr_t tempFloat2M;
133
  mpfr_prec_t prec;
134
  int64_t asInt;
135
  sollya_obj_t newConstantSo = NULL;
136
  /* Arguments check. */
137
  if (exprSo == NULL)
138
  {
139
    pobyso_error_message("pobyso_is_free_var_posze_int_power",
140
                        "NULL_POINTER_ARGUMENT",
141
                        "The expression is a NULL pointer");
142
    return 0;
143
  }
144
  //fprintf(stdout, "Not NULL.\n"); pobyso_autoprint(exprSo);
145
  if (! pobyso_is_constant_expression(exprSo)) return 0;
146
  if (! sollya_lib_get_constant_as_int64(&asInt, exprSo)) return 0;
147
  if (asInt == INT64_MIN || asInt == INT64_MAX) return 0;
148
  /* Some constant integer expression can't have their precision computed
149
   * (e.g. cos(pi). */
150
  if (! sollya_lib_get_prec_of_constant(&prec, exprSo))
151
  {
152
    mpfr_init2(tempFloat1M, 165);
153
    mpfr_init2(tempFloat2M, 165);
154
    mpfr_abs(tempFloat1M, tempFloat1M, MPFR_RNDN);
155
    mpfr_log2(tempFloat2M, tempFloat1M, MPFR_RNDU);
156
    mpfr_rint_ceil(tempFloat1M, tempFloat2M, MPFR_RNDU);
157
    prec = mpfr_get_si(tempFloat1M, MPFR_RNDN) + 10;
158
    if (prec < 1024) prec = 1024;
159
    mpfr_clear(tempFloat1M);
160
    mpfr_clear(tempFloat2M);
161
    mpfr_init2(float1M, prec);
162
    if (!sollya_lib_get_constant(float1M, exprSo))
163
    {
164
      mpfr_clear(float1M);
165
      return 0;
166
    }
167
  }
168
  else /* Precision could be given. */
169
  {
170
    mpfr_init2(float1M, prec);
171
    if (! sollya_lib_get_constant(float1M, exprSo))
172
    {
173
      mpfr_clear(float1M);
174
      return 0;
175
    }
176
  }
177
  if (mpfr_nan_p(float1M) || mpfr_inf_p(float1M))
178
  {
179
    mpfr_clear(float1M);
180
    return 0;
181
  }
182
  if ((newConstantSo = sollya_lib_constant_from_int64(asInt)) == NULL)
183
  {
184
    mpfr_clear(float1M);
185
    return 0;
186
  }
187
  sollya_lib_get_prec_of_constant(&prec, newConstantSo);
188
  mpfr_init2(float2M, prec);
189
  sollya_lib_get_constant(float2M, newConstantSo);
190
  if (mpfr_cmp(float1M, float2M) == 0)
191
  {
192
    mpfr_clear(float1M);
193
    mpfr_clear(float2M);
194
    sollya_lib_clear_obj(newConstantSo);
195
    return 1;
196
  }
197
  else
198
  {
199
    pobyso_autoprint(exprSo);
200
    pobyso_autoprint(newConstantSo);
201
    mpfr_clear(float1M);
202
    mpfr_clear(float2M);
203
    sollya_lib_clear_obj(newConstantSo);
204
    return 0;
205
  }
206
} /* End pobyso_is_int. */
207

    
208
/** @see pobyso.h#pobyso_is_monomial.
209
 * Strategy: check that the object is a functional expression and
210
 * if so check that it is made of cte * free_var ^ some_power where :
211
 * - cte is a constant expression (a per pobyso_is_constant_experession;
212
 * - some_power is a positive or null power. t*/
213
int
214
pobyso_is_monomial(sollya_obj_t objSo)
215
{
216
  return 0;
217
} /* End pobyso_is_monomial. */
218

    
219
/** @see pobyso.h#pobyso_new_monomial. */
220
pobyso_func_exp_t
221
pobyso_new_monomial(pobyso_func_exp_t coefficientSo, long degree)
222
{
223
  sollya_obj_t degreeSo   = NULL;
224
  sollya_obj_t varToPowSo = NULL;
225
  sollya_obj_t monomialSo = NULL;
226
  int initial_verbosity_level = 0;
227

    
228
  /* Arguments check. */
229
  if (coefficientSo == NULL)
230
  {
231
    pobyso_error_message("pobyso_parse_string",
232
                        "NULL_POINTER_ARGUMENT",
233
                        "The expression is a NULL pointer");
234
    return NULL;
235
  }
236
  if (! pobyso_is_constant_expression(coefficientSo))
237
  {
238
    return NULL;
239
  }
240
  if (degree < 0)
241
  {
242
    pobyso_error_message("pobyso_new_monomial",
243
                        "NEGATIVE_DEGREE_ARGUMENT",
244
                        "The degree is a negative integer");
245
    return NULL;
246
  }
247
  /* If degree == 0, just return a copy of the coefficient. Do not
248
   * return the coefficient itself to avoid "double clear" issues. */
249
  if (degree == 0)
250
  {
251
    initial_verbosity_level = pobyso_set_verbosity_off();
252
    monomialSo = sollya_lib_copy_obj(coefficientSo);
253
    pobyso_set_verbosity_to(initial_verbosity_level);
254
  }
255
  degreeSo    = sollya_lib_constant_from_int64(degree);
256
  varToPowSo  = sollya_lib_build_function_pow(sollya_lib_free_variable(),
257
                                              degreeSo);
258
  /* Do not use the "build" version to avoid "eating up" the coefficient. */
259
  monomialSo = sollya_lib_mul(coefficientSo,varToPowSo);
260
  sollya_lib_clear_obj(varToPowSo);
261
  /* Do not clear degreeSa: it was "eaten" by sollya-lib_build_function. */
262
  return monomialSo;
263
} /* End pobyso_new_monomial. */
264

    
265
/* @see pobyso.h#pobyso_parse_string*/
266
pobyso_func_exp_t
267
pobyso_parse_string(const char* expression)
268
{
269
  int expressionLength, i;
270
  char *expressionWithSemiCo;
271
  sollya_obj_t expressionSo;
272

    
273
  /* Arguments check. */
274
  if (expression == NULL)
275
  {
276
    pobyso_error_message("pobyso_parse_string",
277
                        "NULL_POINTER_ARGUMENT",
278
                        "The expression is a NULL pointer");
279
    return  NULL;
280
  }
281
  expressionLength = strlen(expression);
282
  if (expressionLength == 0)
283
  {
284
    pobyso_error_message("pobyso_parse_string",
285
                        "EMPTY_STRING_ARGUMENT",
286
                        "The expression is an empty string");
287
    return NULL;
288
  }
289
  /* Search from the last char of the expression until, whichever happens
290
   * first:
291
   * a ";" is found;
292
   * a char  != ';' is found the the ";" is appended.
293
   * If the head of the string is reached before any of these two events happens
294
   * return an error.
295
   */
296
  for (i = expressionLength - 1 ; i >= 0 ; i--)
297
  {
298
    if (expression[i] == ';') /* Nothing special to do:
299
                                 try to parse the string*/
300
    {
301
      expressionSo = sollya_lib_parse_string(expression);
302
      if (sollya_lib_obj_is_error(expressionSo))
303
      {
304
        sollya_lib_clear_obj(expressionSo);
305
        return NULL;
306
      }
307
      else
308
      {
309
        return expressionSo;
310
      }
311
    }
312
    else
313
    {
314
      if (expression[i] == ' ' || expression[i] == '\t') /* A blank,
315
                                                           just continue. */
316
      {
317
        continue;
318
      }
319
      else /* a character != ';' and from a blank: create the ';'ed string. */
320
      {
321
        /* Create a new string for the expression, add the ";" and
322
         * and call sollya_lib_parse_string. */
323
        expressionWithSemiCo = calloc(i + 3, sizeof(char));
324
        if (expressionWithSemiCo == NULL)
325
        {
326
          pobyso_error_message("pobyso_parse_string",
327
                                "MEMORY_ALLOCATION_ERROR",
328
                                "Could not allocate the expression string");
329
          return NULL;
330
        }
331
        strncpy(expressionWithSemiCo, expression, i+1);
332
        expressionWithSemiCo[i + 1] = ';';
333
        expressionWithSemiCo[i + 2] = '\0';
334
        expressionSo = sollya_lib_parse_string(expressionWithSemiCo);
335
        free(expressionWithSemiCo);
336
        if (sollya_lib_obj_is_error(expressionSo))
337
        {
338
          sollya_lib_clear_obj(expressionSo);
339
          return NULL;
340
        }
341
        else
342
        {
343
          return expressionSo;
344
        }
345
      } /* End character != ';' and from a blank. */
346
    /* Create a new string for the expression, add the ";" and
347
     * and call sollya_lib_parse_string. */
348
    } /* End else. */
349
  } /* End for. */
350
  /* We get here, it is because we did not find any char == anything different
351
   * from ' ' or '\t': the string is empty.
352
   */
353
  pobyso_error_message("pobyso_parse_string",
354
                       "ONLY_BLANK_ARGUMENT",
355
                        "The expression is only made of blanks");
356
  return NULL;
357
} /* pobyso_parse_string */
358

    
359
pobyso_func_exp_t
360
pobyso_remez_canonical_monomials_base(pobyso_func_exp_t function,
361
                                      long int degree,
362
                                      pobyso_range_t interval,
363
                                      pobyso_func_exp_t weight,
364
                                      double quality,
365
                                      pobyso_range_t bounds)
366
{
367
  sollya_obj_t  degreeSo = NULL;
368
  sollya_obj_t qualitySo = NULL;
369

    
370
  degreeSo = sollya_lib_constant_from_int(degree);
371
  qualitySo = sollya_lib_constant_from_double(quality);
372

    
373
  sollya_lib_clear_obj(degreeSo);
374
  sollya_lib_clear_obj(qualitySo);
375
  return NULL;
376
} /* End pobyso_remez_canonical_monomials_base. */
377

    
378
int
379
pobyso_set_canonical_on()
380
{
381
  pobyso_on_off_t currentCanonicalModeSo;
382
  pobyso_on_off_t on;
383

    
384
  currentCanonicalModeSo = sollya_lib_get_canonical();
385
  if (sollya_lib_is_on(currentCanonicalModeSo))
386
  {
387
    sollya_lib_clear_obj(currentCanonicalModeSo);
388
    return POBYSO_ON;
389
  }
390
  else
391
  {
392
    on = sollya_lib_on();
393
    sollya_lib_set_canonical(on);
394
    sollya_lib_clear_obj(on);
395
    sollya_lib_clear_obj(currentCanonicalModeSo);
396
    return POBYSO_OFF;
397
  }
398
} /* End pobyso_set_canonical_on. */
399

    
400
int
401
pobyso_set_verbosity_off()
402
{
403
  sollya_obj_t verbosityLevelZeroSo;
404
  sollya_obj_t currentVerbosityLevelSo = NULL;
405
  int currentVerbosityLevel = 0;
406

    
407
  currentVerbosityLevelSo = sollya_lib_get_verbosity();
408
  sollya_lib_get_constant_as_int(&currentVerbosityLevel,
409
                                 currentVerbosityLevelSo);
410
  verbosityLevelZeroSo = sollya_lib_constant_from_int(0);
411
  sollya_lib_set_verbosity(verbosityLevelZeroSo);
412
  sollya_lib_clear_obj(verbosityLevelZeroSo);
413
  sollya_lib_clear_obj(currentVerbosityLevelSo);
414
  return currentVerbosityLevel;
415
} /* End of pobyso_set_verbosity_off. */
416

    
417
int
418
pobyso_set_verbosity_to(int newVerbosityLevel)
419
{
420
  int initialVerbosityLevel = 0;
421
  sollya_obj_t initialVerbosityLevelSo = NULL;
422
  sollya_obj_t newVerbosityLevelSo = NULL;
423

    
424
  initialVerbosityLevelSo = sollya_lib_get_verbosity();
425
  sollya_lib_get_constant_as_int(&initialVerbosityLevel,
426
                                 initialVerbosityLevelSo);
427
  sollya_lib_clear_obj(initialVerbosityLevelSo);
428
  if (newVerbosityLevel < 0)
429
  {
430
    pobyso_error_message("pobyso_set_verbosity_to",
431
                        "INVALID_VALUE",
432
                        "The new verbosity level is a negative number");
433
    return initialVerbosityLevel;
434
  }
435
  newVerbosityLevelSo = sollya_lib_constant_from_int(newVerbosityLevel);
436
  sollya_lib_set_verbosity(newVerbosityLevelSo);
437
  sollya_lib_clear_obj(newVerbosityLevelSo);
438
  return initialVerbosityLevel;
439
} /* End of pobyso_set_verbosity_to. */
440

    
441
/**
442
 * @see pobyso.h#pobyso_subpoly
443
 */
444
pobyso_func_exp_t
445
pobyso_subpoly(pobyso_func_exp_t polynomialSo, long expsNum, long int* expsList)
446
{
447
  sollya_obj_t  expsListSo    = NULL;
448
  sollya_obj_t* expsList_pso  = NULL;
449
  sollya_obj_t subpoly        = NULL;
450
  int i, j;
451

    
452
  /* Arguments check. */
453
  if (polynomialSo == NULL) return NULL;
454
  if (expsNum < 0) return NULL;
455
  if (expsNum == 0) return sollya_lib_copy_obj(polynomialSo);
456
  if (expsList == 0) return NULL;
457
  /* Create a list of Sollya constants. */
458
  expsList_pso = (sollya_obj_t*) malloc(expsNum * sizeof(sollya_obj_t));
459
  if (expsList_pso == NULL)
460
  {
461
    pobyso_error_message("pobyso_subpoly",
462
                          "MEMORY_ALLOCATION_ERROR",
463
                          "Could not allocate the Sollya exponents list");
464
    return NULL;
465
  }
466
  /* Fill up the list. */
467
  for (i = 0 ; i < expsNum ; i++)
468
  {
469
    /* Abort if an exponent is negative. */
470
    if (expsList[i] < 0 )
471
    {
472
      for (j = 0 ; j < i ; j++)
473
      {
474
        sollya_lib_clear_obj(expsList_pso[j]);
475
      }
476
      free(expsList_pso);
477
      return NULL;
478
    }
479
    expsList_pso[i] = sollya_lib_constant_from_int64(expsList[i]);
480
  } /* End for */
481
  expsListSo = sollya_lib_list(expsList_pso, expsNum);
482
  for (i = 0 ; i < expsNum ; i++)
483
  {
484
    sollya_lib_clear_obj(expsList_pso[i]);
485
  }
486
  free(expsList_pso);
487
  if (expsListSo == NULL)
488
  {
489
    pobyso_error_message("pobyso_subpoly",
490
                          "LIST_CREATIONERROR",
491
                          "Could not create the exponents list");
492
    return NULL;
493
  }
494
  subpoly = sollya_lib_subpoly(polynomialSo, expsListSo);
495
  pobyso_autoprint(expsListSo);
496
  sollya_lib_clear_obj(expsListSo);
497
  return subpoly;
498
} /* pobyso_subpoly. */
499

    
500
/* Attic from the sollya_lib < 4. */
501
#if 0
502
chain*
503
pobyso_create_canonical_monomials_base(const unsigned int degree)
504
{
505
  int i    = 0;
506
  chain *monomials  = NULL;
507
  node  *monomial   = NULL;
508

509
  for(i = degree ; i >= 0  ; i--)
510
  {
511
     monomial   = makePow(makeVariable(), makeConstantDouble((double)i));
512
     monomials  = addElement(monomials, monomial);
513
     fprintf(stderr, "pobyso_create_canonical_monomials_base: %u\n", i);
514
  }
515
  if (monomials == NULL)
516
  {
517
    pobyso_error_message("pobyso_create_canonical_monomial_base",
518
                        "CHAIN_CREATION_ERROR",
519
                        "Could not create the monomials chain");
520
    return(NULL);
521
  }
522
  return(monomials);
523
} /* End pobyso_create_canonical_monomials_base. */
524

525
chain*
526
pobyso_create_chain_from_int_array(int* intArray,
527
                                    const unsigned int arrayLength)
528
{
529
  int i = 0;
530
  chain *newChain = NULL;
531
  int *currentInt;
532

533
  if (arrayLength == 0) return(NULL);
534
  if (intArray == NULL)
535
  {
536
    pobyso_error_message("pobyso_create_chain_from_int_array",
537
                        "NULL_POINTER_ARGUMENT",
538
                        "The array is a NULL pointer");
539
    return(NULL);
540
  }
541
  for (i = arrayLength - 1 ; i >= 0 ; i--)
542
  {
543
    currentInt = malloc(sizeof(int));
544
    if (currentInt == NULL)
545
    {
546
      pobyso_error_message("pobyso_create_chain_from_int_array",
547
                          "MEMORY_ALLOCATION_ERROR",
548
                          "Could not allocate one of the integers");
549
      freeChain(newChain, free);
550
      return(NULL);
551
    }
552
    *currentInt = intArray[i];
553
    newChain = addElement(newChain, currentInt);
554
  }
555
  return(newChain);
556
} // End pobyso_create_chain_from_int_array. */
557

558
chain*
559
pobyso_create_chain_from_unsigned_int_array(unsigned int* intArray,
560
                                        const unsigned int arrayLength)
561
{
562
  int i = 0;
563
  chain *newChain = NULL;
564
  unsigned int *currentInt;
565

566
  /* Argument checking. */
567
  if (arrayLength == 0) return(NULL);
568
  if (intArray == NULL)
569
  {
570
    pobyso_error_message("pobyso_create_chain_from_unsigned_int_array",
571
                        "NULL_POINTER_ARGUMENT",
572
                        "The array is a NULL pointer");
573
    return(NULL);
574
  }
575
  for (i = arrayLength - 1 ; i >= 0 ; i--)
576
  {
577
    currentInt = malloc(sizeof(unsigned int));
578
    if (currentInt == NULL)
579
    {
580
      pobyso_error_message("pobyso_create_chain_from_unsigned_int_array",
581
                          "MEMORY_ALLOCATION_ERROR",
582
                          "Could not allocate one of the integers");
583
      freeChain(newChain, free);
584
      return(NULL);
585
    }
586
    *currentInt = intArray[i];
587
    newChain = addElement(newChain, currentInt);
588
  }
589
  return(newChain);
590
} // End pobyso_create_chain_from_unsigned_int_array. */
591

592
node*
593
pobyso_differentiate(node *functionNode)
594
{
595
  /* Argument checking. */
596
  node *differentialNode;
597
  if (functionNode == NULL)
598
  {
599
    pobyso_error_message("pobyso_differentiate",
600
                        "NULL_POINTER_ARGUMENT",
601
                        "The function to differentiate is a NULL pointer");
602
    return(NULL);
603
  }
604
  differentialNode = differentiate(functionNode);
605
  if (differentialNode == NULL)
606
  {
607
    pobyso_error_message("pobyso_differentiate",
608
                        "INTERNAL ERROR",
609
                        "Sollya could not differentiate the function");
610
  }
611
  return(differentialNode);
612
} // End pobyso_differentiate
613

614

615
int
616
pobyso_dirty_infnorm(mpfr_t infNorm,
617
                      node *functionNode,
618
                      mpfr_t lowerBound,
619
                      mpfr_t upperBound,
620
                      mp_prec_t precision)
621
{
622
  int functionCallResult;
623
  /* Arguments checking. */
624
  if (functionNode == NULL)
625
  {
626
    pobyso_error_message("pobyso_dirty_infnorm",
627
                        "NULL_POINTER_ARGUMENT",
628
                        "The function to compute is a NULL pointer");
629
    return(1);
630
  }
631
  if (mpfr_cmp(lowerBound, upperBound) > 0)
632
  {
633
    pobyso_error_message("pobyso_dirty_infnorm",
634
                        "INCOHERENT_INPUT_DATA",
635
                        "The lower bond is greater than the upper bound");
636
    return(1);
637
  }
638
  /* Particular cases. */
639
  if (mpfr_cmp(lowerBound, upperBound) == 0)
640
  {
641
    functionCallResult = pobyso_evaluate_faithful(infNorm,
642
                                                  functionNode,
643
                                                  lowerBound,
644
                                                  precision);
645
    return(functionCallResult);
646
  }
647
  if (isConstant(functionNode))
648
  {
649
    functionCallResult = pobyso_evaluate_faithful(infNorm,
650
                                                  functionNode,
651
                                                  lowerBound,
652
                                                  precision);
653
    if (!functionCallResult)
654
    {
655
      mpfr_abs(infNorm, infNorm, MPFR_RNDN);
656
    }
657
    return(functionCallResult);
658
  }
659
  uncertifiedInfnorm(infNorm,
660
                      functionNode,
661
                      lowerBound,
662
                      upperBound,
663
                      POBYSO_DEFAULT_POINTS,
664
                      precision);
665
  return(0);
666
} /* End pobyso_dirty_infnorm. */
667

668
int
669
pobyso_evaluate_faithful(mpfr_t faithfulEvaluation,
670
                          node *nodeToEvaluate,
671
                          mpfr_t argument,
672
                          mpfr_prec_t precision)
673
{
674
  /* Check input arguments. */
675
  if (nodeToEvaluate == NULL)
676
  {
677
    pobyso_error_message("pobyso_evaluate_faithful",
678
                        "NULL_POINTER_ARGUMENT",
679
                        "nodeToEvaluate is a NULL pointer");
680
    return(1);
681
  }
682
  evaluateFaithful(faithfulEvaluation,
683
                   nodeToEvaluate,
684
                   argument,
685
                   precision);
686
  return(0);
687
} /* End pobyso_evaluate_faithfull. */
688

689
chain*
690
pobyso_find_zeros(node *function,
691
                  mpfr_t *lower_bound,
692
                  mpfr_t *upper_bound)
693
{
694
  mp_prec_t currentPrecision;
695
  mpfr_t currentDiameter;
696
  rangetype bounds;
697

698
  currentPrecision = getToolPrecision();
699
  mpfr_init2(currentDiameter, currentPrecision);
700

701
  bounds.a = lower_bound;
702
  bounds.b = upper_bound;
703

704
  if (bounds.a == NULL || bounds.b == NULL)
705
  {
706
    pobyso_error_message("pobyso_find_zeros",
707
                        "MEMORY_ALLOCATION_ERROR",
708
                        "Could not allocate one of the bounds");
709
    return(NULL);
710
  }
711
  return(findZerosFunction(function,
712
                            bounds,
713
                            currentPrecision,
714
                            currentDiameter));
715
} /* End pobyso_find_zeros. */
716

717
void
718
pobyso_free_chain_of_nodes(chain *theChainOfNodes)
719
{
720
  node *currentNode           = NULL;
721
  chain *currentChainElement  = NULL;
722
  chain *nextChainElement     = NULL;
723

724
  nextChainElement = theChainOfNodes;
725

726
  while(nextChainElement != NULL)
727
  {
728
    currentChainElement = nextChainElement;
729
    currentNode = (node*)(currentChainElement->value);
730
    nextChainElement = nextChainElement->next;
731
    free_memory(currentNode);
732
    free((void*)(currentChainElement));
733
  }
734
} /* End pobyso_free_chain_of_nodes. */
735

736
void
737
pobyso_free_range(rangetype range)
738
{
739

740
  mpfr_clear(*(range.a));
741
  mpfr_clear(*(range.b));
742
  free(range.a);
743
  free(range.b);
744
} /* End pobyso_free_range. */
745

746
node*
747
pobyso_fp_minimax_canonical_monomials_base(node *function,
748
                                      int degree,
749
                                      chain *formats,
750
                                      chain *points,
751
                                      mpfr_t lowerBound,
752
                                      mpfr_t upperBound,
753
                                      int fpFixedArg,
754
                                      int absRel,
755
                                      node *constPart,
756
                                      node *minimax)
757
{
758
  return(NULL);
759
} /* End pobyso_fp_minimax_canonical_monomials_base. */
760

761
node*
762
pobyso_parse_function(char *functionString,
763
                      char *freeVariableNameString)
764
{
765
  if (functionString == NULL || freeVariableNameString == NULL)
766
  {
767
    pobyso_error_message("pobyso_parse_function",
768
                        "NULL_POINTER_ARGUMENT",
769
                        "One of the arguments is a NULL pointer");
770
    return(NULL);
771
  }
772
  return(parseString(functionString));
773

774
} /* End pobyso_parse_function */
775

776
node*
777
pobyso_remez_approx_canonical_monomials_base_for_error(node *functionNode,
778
                                                  unsigned int mode,
779
                                                  mpfr_t lowerBound,
780
                                                  mpfr_t upperBound,
781
                                                  mpfr_t eps)
782
{
783
  node *weight              = NULL;
784
  node *bestApproxPolyNode  = NULL;
785
  node *bestApproxHorner    = NULL;
786
  node *errorNode           = NULL;
787
  rangetype degreeRange;
788
  mpfr_t quality;
789
  mpfr_t currentError;
790
  unsigned int degree;
791

792
  /* Check the parameters. */
793
  if (functionNode == NULL)
794
  {
795
    pobyso_error_message("remezApproxCanonicalMonomialsBaseForError",
796
                        "NULL_POINTER_ARGUMENT",
797
                        "functionNode is a NULL pointer");
798
    return(NULL);
799
  }
800
  if (mpfr_cmp(lowerBound, upperBound) >= 0)
801
  {
802
    pobyso_error_message("remezApproxCanonicalMonomialsBaseForError",
803
                        "INCOHERENT_INPUT_DATA",
804
                        "the lower_bound >= upper_bound");
805
    return(NULL);
806
  }
807
  /* Set the weight. */
808
  if (mode == POBYSO_ABSOLUTE)
809
  {
810
    /* Set the weight to 1 for the ABSOLUTE_MODE. */
811
    weight = makeConstantDouble(1.0);
812
  }
813
  else
814
  {
815
    if (mode == POBYSO_RELATIVE)
816
    {
817
      pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
818
                          "NOT_IMPLEMENTED",
819
                          "the search for relative error is not implemented yet");
820
      return(NULL);
821
    }
822
    else
823
    {
824
      pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
825
                          "INCOHERENT_INPUT_DATA",
826
                          "the mode is node of POBYSO_ABOLUTE or POBYSO_RELATIVE");
827
      return(NULL);
828
    }
829
  }
830
  //fprintf(stderr, "\n\n\n******* I'm here! ********\n\n\n");
831
  degreeRange = guessDegree(functionNode,
832
                            weight,
833
                            lowerBound,
834
                            upperBound,
835
                            eps,
836
                            POBYSO_GUESS_DEGREE_BOUND);
837
  degree = mpfr_get_ui(*(degreeRange.a), MPFR_RNDN);
838
  //fprintf(stderr, "\n\n\n******* I'm back! ********\n\n\n");
839
  fprintf(stderr, "Guessed degree: ");
840
  mpfr_out_str(stderr, 10, 17, *(degreeRange.a), MPFR_RNDN);
841
  fprintf(stderr, " - as int: %u\n", degree);
842
  /* Reduce the degree by 1 in the foolish hope it could work. */
843
  if (degree > 0) degree--;
844
  /* Both elements of degreeRange where "inited" within guessDegree. */
845
  mpfr_clear(*(degreeRange.a));
846
  mpfr_clear(*(degreeRange.b));
847
  free(degreeRange.a);
848
  free(degreeRange.b);
849
  /* Mimic the default behavior of interactive Sollya. */
850
  mpfr_init(quality);
851
  mpfr_set_d(quality, 1e-5, MPFR_RNDN);
852
  mpfr_init2(currentError, getToolPrecision());
853
  mpfr_set_inf(currentError,1);
854

855
  /* Try to refine the initial guess: loop with increasing degrees until
856
   * we find a satisfactory one. */
857
  while(mpfr_cmp(currentError, eps) > 0)
858
  {
859
    /* Get rid of the previous polynomial, if any. */
860
    if (bestApproxPolyNode != NULL)
861
    {
862
      free_memory(bestApproxPolyNode);
863
    }
864
    fprintf(stderr, "Degree: %u\n", degree);
865
    fprintf(stderr, "Calling pobyso_remez_canonical_monomials_base...\n");
866
    /* Try to find a polynomial with the guessed degree. */
867
    bestApproxPolyNode = pobyso_remez_canonical_monomials_base(functionNode,
868
                                                            weight,
869
                                                            degree,
870
                                                            lowerBound,
871
                                                            upperBound,
872
                                                            quality);
873

874
    if (bestApproxPolyNode == NULL)
875
    {
876
      pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
877
                          "INTERNAL_ERROR",
878
                          "could not compute the bestApproxPolyNode");
879
      mpfr_clear(currentError);
880
      mpfr_clear(quality);
881
      return(NULL);
882
    }
883

884
    setDisplayMode(DISPLAY_MODE_DECIMAL);
885
    fprintTree(stderr, bestApproxPolyNode);
886
    fprintf(stderr, "\n\n");
887

888
    errorNode = makeSub(copyTree(functionNode), copyTree(bestApproxPolyNode));
889
    /* Check the error with the computed polynomial. */
890
    uncertifiedInfnorm(currentError,
891
                        errorNode,
892
                        lowerBound,
893
                        upperBound,
894
                        POBYSO_INF_NORM_NUM_POINTS,
895
                        getToolPrecision());
896
    fprintf(stderr, "Inf norm: ");
897
    mpfr_out_str(stderr, 10, 17, currentError, MPFR_RNDN);
898
    fprintf(stderr, "\n\n");
899
    /* Free the errorNode but not the bestApproxPolyNode (we need it if
900
     * we exit the loop at the next iteration). */
901
    free_memory(errorNode);
902
    degree++;
903
  }
904
  /* Use an intermediate variable, since horner() creates a new node
905
   * and does not reorder the argument "in place". This allows for the memory
906
   * reclaim of bestApproxHorner.
907
   */
908
  bestApproxHorner = horner(bestApproxPolyNode);
909
  free_memory(bestApproxPolyNode);
910
  mpfr_clear(currentError);
911
  mpfr_clear(quality);
912
  free_memory(weight);
913
  return(bestApproxHorner);
914
} /* End pobyso_remez_approx_canonical_monomials_base_for_error */
915

916
node*
917
pobyso_remez_canonical_monomials_base(node *function,
918
                                     node *weight,
919
                                     unsigned int degree,
920
                                     mpfr_t lowerBound,
921
                                     mpfr_t upperBound,
922
                                     mpfr_t quality)
923
{
924
  node  *bestApproxPoly = NULL;
925
  chain *monomials      = NULL;
926
  chain *curMonomial    = NULL;
927

928
  mpfr_t satisfying_error;
929
  mpfr_t target_error;
930

931
  /* Argument checking */
932
  /* Function tree. */
933
  if (function == NULL)
934
  {
935
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
936
                        "NULL_POINTER_ARGUMENT",
937
                        "the \"function\" argument is a NULL pointer");
938
    return(NULL);
939
  }
940
  if (weight == NULL)
941
  {
942
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
943
                        "NULL_POINTER_ARGUMENT",
944
                        "the \"weight\" argument is a NULL pointer");
945
    return(NULL);
946
  }
947
  /* Check the bounds. */
948
  if (mpfr_cmp(lowerBound, upperBound) >= 0)
949
  {
950
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
951
                        "INCOHERENT_IMPUT_DATA",
952
                        "the lower_bound >= upper_bound");
953
    return(NULL);
954
  }
955
  /* The quality must be a non null positive number. */
956
  if (mpfr_sgn(quality) <= 0)
957
  {
958
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
959
                        "INCOHERENT_INPUT_DATA",
960
                        "the quality <= 0");
961
  }
962
  /* End argument checking. */
963
  /* Create the monomials nodes chains. */
964
  monomials = pobyso_create_canonical_monomials_base(degree);
965
  fprintf(stderr, "monomials chain length = %d\n", lengthChain(monomials));
966
  if (monomials == NULL || (lengthChain(monomials) != degree + 1))
967
  {
968
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
969
                        "CHAIN_CREATION_ERROR",
970
                        "could not create the monomials chain");
971
    return(NULL);
972
  }
973
  curMonomial = monomials;
974

975
  while (curMonomial != NULL)
976
  {
977
    fprintf(stderr, "monomial tree: ");
978
    //mpfr_out_str(stderr, 10, 17, *((mpfr_t*)((node*)(curMonomial->value))->value), MPFR_RNDN);
979
    fprintTree(stderr, (node*)(curMonomial->value));
980
    fprintf(stderr, "\n");
981
    curMonomial = curMonomial->next;
982
  }
983

984
  /* Deal with NULL weight. */
985
  if (weight == NULL)
986
  {
987
    weight = makeConstantDouble(1.0);
988
  }
989
  /* Compute the best polynomial with the required quality.
990
     The behavior is as if satisfying error and target_error had
991
     not been used.*/
992
  mpfr_init(satisfying_error);
993
  mpfr_init(target_error);
994
  mpfr_set_str(satisfying_error, "0", 10, MPFR_RNDN);
995
  mpfr_set_inf(target_error, 1);
996

997

998
  fprintf(stderr, "satisfying_error: ");
999
  mpfr_out_str(stderr, 10, 17, satisfying_error, MPFR_RNDN);
1000
  fprintf(stderr, ".\n");
1001
  fprintf(stderr, "target_error: ");
1002
  mpfr_out_str(stderr, 10, 17, target_error,MPFR_RNDN);
1003
  fprintf(stderr, ".\n");
1004

1005
  fprintf(stderr,
1006
          "current precision: %li\n", getToolPrecision());
1007
  /* Call the Sollya function. */
1008
  bestApproxPoly = remez(function,
1009
                          weight,
1010
                          monomials,
1011
                          lowerBound,
1012
                          upperBound,
1013
                          quality,
1014
                          satisfying_error,
1015
                          target_error,
1016
                          getToolPrecision());
1017

1018
  mpfr_clear(satisfying_error);
1019
  mpfr_clear(target_error);
1020
  pobyso_free_chain_of_nodes(monomials);
1021

1022
  return(bestApproxPoly);
1023
} /* End pobyso_remez_canonical_monomials_base. */
1024

1025
#endif
1026

    
1027
void
1028
pobyso_error_message(char *functionName, char *messageName, char* message)
1029
{
1030
  fprintf(stderr, "?%s: %s.\n%s.\n", functionName, messageName, message);
1031
} /* End pobyso_error_message */