Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (36,36 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
  pobyso_set_verbosity_to(initial_verbosity_level);
87
  if (test)
88
  {
89
    if(mpfr_number_p(dummy))
90
    {
91
      mpfr_clear(dummy);
92
      return test;
93
    }
94
    else
95
    {
96
      mpfr_clear(dummy);
97
      return 0;
98
    }
99
  }
100
  else
101
  {
102
    return 0;
103
  }
104
} /* End pobyso_is_constant_expression. */
105

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

    
187
/** @see pobyso.h#pobyso_is_monomial.
188
 * Strategy: check that the object is a functional expression and
189
 * if so check that it is made of cte * free_var ^ some_power where :
190
 * - cte is a constant expression (a per pobyso_is_constant_experession;
191
 * - some_power is a positive or null power. t*/
192
int
193
pobyso_is_monomial(sollya_obj_t objSo)
194
{
195
  int arity;
196
  sollya_obj_t subFun1So = NULL;
197
  sollya_obj_t subFun2So = NULL;
198
  sollya_obj_t subFun3So = NULL;
199
  sollya_base_function_t head = 0;
200
  long int exponent = 0;
201
  long int exprIntValue = 0;
202

    
203
  /* Arguments check. */
204
  if (objSo == NULL)
205
  {
206
    pobyso_error_message("pobyso_is_monomial",
207
                        "NULL_POINTER_ARGUMENT",
208
                        "The expression is a NULL pointer");
209
    return 0;
210
  }
211
  /* The object must be a function. */
212
  if (! sollya_lib_obj_is_function(objSo)) return 0;
213
  /* Check if it is the 1 constant. */
214
  if (pobyso_is_int(objSo))
215
  {
216
    if (! sollya_lib_get_constant_as_int64(&exprIntValue, objSo))
217
    {
218
      return 0;
219
    }
220
    else
221
    {
222
      if (exprIntValue == 1) return 1;
223
      else return 0;
224
    }
225
  }
226
  if (! sollya_lib_decompose_function(objSo,
227
                                      &head,
228
                                      &arity,
229
                                      &subFun1So,
230
                                      &subFun2So,
231
                                      NULL)) return 0;
232
  if (arity > 2)
233
  {
234
    if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
235
    if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
236
    return 0;
237
  }
238
  /* Arity == 1 must be free variable by itself. */
239
  if (arity == 1 && head == SOLLYA_BASE_FUNC_FREE_VARIABLE)
240
  {
241
    if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
242
    if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
243
    return 1;
244
  }
245
  else
246
  {
247
    /* Another expression. Must be: free variable  ^ poze integer. */
248
    if (arity == 2)
249
    {
250
      if (head != SOLLYA_BASE_FUNC_POW)
251
      {
252
        if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
253
        if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
254
        return 0;
255
      }
256
      if (! pobyso_is_int(subFun2So))
257
      {
258
        if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
259
        if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
260
        return 0;
261
      }
262
      if (! sollya_lib_get_constant_as_int64(&exponent, subFun2So))
263
      {
264
        if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
265
        if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
266
        return 0;
267
      }
268
      if (exponent < 0)
269
      {
270
        if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
271
        if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
272
        return 0;
273
      }
274
      if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
275
      /* Check that the first subfunction is the free variable. */
276
      if (! sollya_lib_decompose_function(subFun1So,
277
                                          &head,
278
                                          &arity,
279
                                          &subFun2So,
280
                                          &subFun3So,
281
                                          NULL))
282
      {
283
        if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
284
        return 0;
285
      }
286
      if (arity == 1 && head == SOLLYA_BASE_FUNC_FREE_VARIABLE)
287
      {
288
        if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
289
        if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
290
        if (subFun3So != NULL) sollya_lib_clear_obj(subFun3So);
291
        return 1;
292
      }
293
      else
294
      {
295
        if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
296
        if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
297
        return 0;
298
      }
299
    } /* End if arity == 2. */
300
  } /* End else if arity == 1. */
301
  return 0;
302
} /* End pobyso_is_monomial. */
303

    
304
/** @see pobyso.h#pobyso_is_polynomial_term.
305
 * Strategy: check that the object is a functional expression and
306
 * if so check that it is made of cte * monomial.
307
 */
308
int
309
pobyso_is_polynomial_term(sollya_obj_t objSo)
310
{
311
  int arity;
312
  sollya_obj_t subFun1So = NULL;
313
  sollya_obj_t subFun2So = NULL;
314
  sollya_base_function_t head = 0;
315

    
316
  /* Arguments check. */
317
  if (objSo == NULL)
318
  {
319
    pobyso_error_message("pobyso_is_polynomial_term",
320
                        "NULL_POINTER_ARGUMENT",
321
                        "The expression is a NULL pointer");
322
    return 0;
323
  }
324
  /* The object must be a function. */
325
  if (! sollya_lib_obj_is_function(objSo)) return 0;
326
  /* A constant expression is degree 0 polynomial term. */
327
  if (pobyso_is_constant_expression(objSo)) return 1;
328
  /* A monomial is a polynomial term. */
329
  if (pobyso_is_monomial(objSo)) return 1;
330
  /* Decompose the functional expression and study the elements. */
331
  if (! sollya_lib_decompose_function(objSo,
332
                                      &head,
333
                                      &arity,
334
                                      &subFun1So,
335
                                      &subFun2So,
336
                                      NULL)) return 0;
337
  /* Monomial case has been dealt with abobe. */
338
  if (arity != 2)
339
  {
340
    if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
341
    if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
342
    return 0;
343
  }
344
  /* The expression must be: cte  * monomial or monomial * cte. */
345
  if (head != SOLLYA_BASE_FUNC_MUL)
346
  {
347
    if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
348
    if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
349
    return 0;
350
  }
351
  if (! pobyso_is_monomial(subFun2So))
352
  {
353
    if (! pobyso_is_constant_expression(subFun2So) ||
354
        ! pobyso_is_monomial(subFun1So))
355
    {
356
      if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
357
      if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
358
      return 0;
359
    }
360
  }
361
  else
362
  {
363
    if (! pobyso_is_constant_expression(subFun1So))
364
    {
365
      if (subFun1So != NULL) sollya_lib_clear_obj(subFun1So);
366
      if (subFun2So != NULL) sollya_lib_clear_obj(subFun2So);
367
      return 0;
368
    }
369
  }
370
  return 1;
371
} /* End pobyso_is_polynomial_term. */
372
/** @see pobyso.h#pobyso_new_monomial. */
373
pobyso_func_exp_t
374
pobyso_new_monomial(pobyso_func_exp_t coefficientSo, long degree)
375
{
376
  sollya_obj_t degreeSo   = NULL;
377
  sollya_obj_t varToPowSo = NULL;
378
  sollya_obj_t monomialSo = NULL;
379
  int initial_verbosity_level = 0;
380

    
381
  /* Arguments check. */
382
  if (coefficientSo == NULL)
383
  {
384
    pobyso_error_message("pobyso_parse_string",
385
                        "NULL_POINTER_ARGUMENT",
386
                        "The expression is a NULL pointer");
387
    return NULL;
388
  }
389
  if (! pobyso_is_constant_expression(coefficientSo))
390
  {
391
    return NULL;
392
  }
393
  if (degree < 0)
394
  {
395
    pobyso_error_message("pobyso_new_monomial",
396
                        "NEGATIVE_DEGREE_ARGUMENT",
397
                        "The degree is a negative integer");
398
    return NULL;
399
  }
400
  /* If degree == 0, just return a copy of the coefficient. Do not
401
   * return the coefficient itself to avoid "double clear" issues. */
402
  if (degree == 0)
403
  {
404
    initial_verbosity_level = pobyso_set_verbosity_off();
405
    monomialSo = sollya_lib_copy_obj(coefficientSo);
406
    pobyso_set_verbosity_to(initial_verbosity_level);
407
  }
408
  degreeSo    = sollya_lib_constant_from_int64(degree);
409
  varToPowSo  = sollya_lib_build_function_pow(sollya_lib_free_variable(),
410
                                              degreeSo);
411
  /* Do not use the "build" version to avoid "eating up" the coefficient. */
412
  monomialSo = sollya_lib_mul(coefficientSo,varToPowSo);
413
  sollya_lib_clear_obj(varToPowSo);
414
  /* Do not clear degreeSa: it was "eaten" by sollya-lib_build_function. */
415
  return monomialSo;
416
} /* End pobyso_new_monomial. */
417

    
418
/* @see pobyso.h#pobyso_parse_string*/
419
pobyso_func_exp_t
420
pobyso_parse_string(const char* expression)
421
{
422
  int expressionLength, i;
423
  char *expressionWithSemiCo;
424
  sollya_obj_t expressionSo;
425

    
426
  /* Arguments check. */
427
  if (expression == NULL)
428
  {
429
    pobyso_error_message("pobyso_parse_string",
430
                        "NULL_POINTER_ARGUMENT",
431
                        "The expression is a NULL pointer");
432
    return  NULL;
433
  }
434
  expressionLength = strlen(expression);
435
  if (expressionLength == 0)
436
  {
437
    pobyso_error_message("pobyso_parse_string",
438
                        "EMPTY_STRING_ARGUMENT",
439
                        "The expression is an empty string");
440
    return NULL;
441
  }
442
  /* Search from the last char of the expression until, whichever happens
443
   * first:
444
   * a ";" is found;
445
   * a char  != ';' is found the the ";" is appended.
446
   * If the head of the string is reached before any of these two events happens
447
   * return an error.
448
   */
449
  for (i = expressionLength - 1 ; i >= 0 ; i--)
450
  {
451
    if (expression[i] == ';') /* Nothing special to do:
452
                                 try to parse the string*/
453
    {
454
      expressionSo = sollya_lib_parse_string(expression);
455
      if (sollya_lib_obj_is_error(expressionSo))
456
      {
457
        sollya_lib_clear_obj(expressionSo);
458
        return NULL;
459
      }
460
      else
461
      {
462
        return expressionSo;
463
      }
464
    }
465
    else
466
    {
467
      if (expression[i] == ' ' || expression[i] == '\t') /* A blank,
468
                                                           just continue. */
469
      {
470
        continue;
471
      }
472
      else /* a character != ';' and from a blank: create the ';'ed string. */
473
      {
474
        /* Create a new string for the expression, add the ";" and
475
         * and call sollya_lib_parse_string. */
476
        expressionWithSemiCo = calloc(i + 3, sizeof(char));
477
        if (expressionWithSemiCo == NULL)
478
        {
479
          pobyso_error_message("pobyso_parse_string",
480
                                "MEMORY_ALLOCATION_ERROR",
481
                                "Could not allocate the expression string");
482
          return NULL;
483
        }
484
        strncpy(expressionWithSemiCo, expression, i+1);
485
        expressionWithSemiCo[i + 1] = ';';
486
        expressionWithSemiCo[i + 2] = '\0';
487
        expressionSo = sollya_lib_parse_string(expressionWithSemiCo);
488
        free(expressionWithSemiCo);
489
        if (sollya_lib_obj_is_error(expressionSo))
490
        {
491
          sollya_lib_clear_obj(expressionSo);
492
          return NULL;
493
        }
494
        else
495
        {
496
          return expressionSo;
497
        }
498
      } /* End character != ';' and from a blank. */
499
    /* Create a new string for the expression, add the ";" and
500
     * and call sollya_lib_parse_string. */
501
    } /* End else. */
502
  } /* End for. */
503
  /* We get here, it is because we did not find any char == anything different
504
   * from ' ' or '\t': the string is empty.
505
   */
506
  pobyso_error_message("pobyso_parse_string",
507
                       "ONLY_BLANK_ARGUMENT",
508
                        "The expression is only made of blanks");
509
  return NULL;
510
} /* pobyso_parse_string */
511

    
512
pobyso_func_exp_t
513
pobyso_remez_canonical_monomials_base(pobyso_func_exp_t function,
514
                                      long int degree,
515
                                      pobyso_range_t interval,
516
                                      pobyso_func_exp_t weight,
517
                                      double quality,
518
                                      pobyso_range_t bounds)
519
{
520
  sollya_obj_t  degreeSo = NULL;
521
  sollya_obj_t qualitySo = NULL;
522

    
523
  degreeSo = sollya_lib_constant_from_int(degree);
524
  qualitySo = sollya_lib_constant_from_double(quality);
525

    
526
  sollya_lib_clear_obj(degreeSo);
527
  sollya_lib_clear_obj(qualitySo);
528
  return NULL;
529
} /* End pobyso_remez_canonical_monomials_base. */
530

    
531
int
532
pobyso_set_canonical_on()
533
{
534
  pobyso_on_off_t currentCanonicalModeSo;
535
  pobyso_on_off_t on;
536

    
537
  currentCanonicalModeSo = sollya_lib_get_canonical();
538
  if (sollya_lib_is_on(currentCanonicalModeSo))
539
  {
540
    sollya_lib_clear_obj(currentCanonicalModeSo);
541
    return POBYSO_ON;
542
  }
543
  else
544
  {
545
    on = sollya_lib_on();
546
    sollya_lib_set_canonical(on);
547
    sollya_lib_clear_obj(on);
548
    sollya_lib_clear_obj(currentCanonicalModeSo);
549
    return POBYSO_OFF;
550
  }
551
} /* End pobyso_set_canonical_on. */
552

    
553
int
554
pobyso_set_verbosity_off()
555
{
556
  sollya_obj_t verbosityLevelZeroSo;
557
  sollya_obj_t currentVerbosityLevelSo = NULL;
558
  int currentVerbosityLevel = 0;
559

    
560
  currentVerbosityLevelSo = sollya_lib_get_verbosity();
561
  sollya_lib_get_constant_as_int(&currentVerbosityLevel,
562
                                 currentVerbosityLevelSo);
563
  verbosityLevelZeroSo = sollya_lib_constant_from_int(0);
564
  sollya_lib_set_verbosity(verbosityLevelZeroSo);
565
  sollya_lib_clear_obj(verbosityLevelZeroSo);
566
  sollya_lib_clear_obj(currentVerbosityLevelSo);
567
  return currentVerbosityLevel;
568
} /* End of pobyso_set_verbosity_off. */
569

    
570
int
571
pobyso_set_verbosity_to(int newVerbosityLevel)
572
{
573
  int initialVerbosityLevel = 0;
574
  sollya_obj_t initialVerbosityLevelSo = NULL;
575
  sollya_obj_t newVerbosityLevelSo = NULL;
576

    
577
  initialVerbosityLevelSo = sollya_lib_get_verbosity();
578
  sollya_lib_get_constant_as_int(&initialVerbosityLevel,
579
                                 initialVerbosityLevelSo);
580
  sollya_lib_clear_obj(initialVerbosityLevelSo);
581
  if (newVerbosityLevel < 0)
582
  {
583
    pobyso_error_message("pobyso_set_verbosity_to",
584
                        "INVALID_VALUE",
585
                        "The new verbosity level is a negative number");
586
    return initialVerbosityLevel;
587
  }
588
  newVerbosityLevelSo = sollya_lib_constant_from_int(newVerbosityLevel);
589
  sollya_lib_set_verbosity(newVerbosityLevelSo);
590
  sollya_lib_clear_obj(newVerbosityLevelSo);
591
  return initialVerbosityLevel;
592
} /* End of pobyso_set_verbosity_to. */
593

    
594
/**
595
 * @see pobyso.h#pobyso_subpoly
596
 */
597
pobyso_func_exp_t
598
pobyso_subpoly(pobyso_func_exp_t polynomialSo, long expsNum, long int* expsList)
599
{
600
  sollya_obj_t  expsListSo    = NULL;
601
  sollya_obj_t* expsList_pso  = NULL;
602
  sollya_obj_t subpoly        = NULL;
603
  int i, j;
604

    
605
  /* Arguments check. */
606
  if (polynomialSo == NULL) return NULL;
607
  if (expsNum < 0) return NULL;
608
  if (expsNum == 0) return sollya_lib_copy_obj(polynomialSo);
609
  if (expsList == 0) return NULL;
610
  /* Create a list of Sollya constants. */
611
  expsList_pso = (sollya_obj_t*) malloc(expsNum * sizeof(sollya_obj_t));
612
  if (expsList_pso == NULL)
613
  {
614
    pobyso_error_message("pobyso_subpoly",
615
                          "MEMORY_ALLOCATION_ERROR",
616
                          "Could not allocate the Sollya exponents list");
617
    return NULL;
618
  }
619
  /* Fill up the list. */
620
  for (i = 0 ; i < expsNum ; i++)
621
  {
622
    /* Abort if an exponent is negative. */
623
    if (expsList[i] < 0 )
624
    {
625
      for (j = 0 ; j < i ; j++)
626
      {
627
        sollya_lib_clear_obj(expsList_pso[j]);
628
      }
629
      free(expsList_pso);
630
      return NULL;
631
    }
632
    expsList_pso[i] = sollya_lib_constant_from_int64(expsList[i]);
633
  } /* End for */
634
  expsListSo = sollya_lib_list(expsList_pso, expsNum);
635
  for (i = 0 ; i < expsNum ; i++)
636
  {
637
    sollya_lib_clear_obj(expsList_pso[i]);
638
  }
639
  free(expsList_pso);
640
  if (expsListSo == NULL)
641
  {
642
    pobyso_error_message("pobyso_subpoly",
643
                          "LIST_CREATIONERROR",
644
                          "Could not create the exponents list");
645
    return NULL;
646
  }
647
  subpoly = sollya_lib_subpoly(polynomialSo, expsListSo);
648
  pobyso_autoprint(expsListSo);
649
  sollya_lib_clear_obj(expsListSo);
650
  return subpoly;
651
} /* pobyso_subpoly. */
652

    
653
/* Attic from the sollya_lib < 4. */
654
#if 0
655
chain*
656
pobyso_create_canonical_monomials_base(const unsigned int degree)
657
{
658
  int i    = 0;
659
  chain *monomials  = NULL;
660
  node  *monomial   = NULL;
661

662
  for(i = degree ; i >= 0  ; i--)
663
  {
664
     monomial   = makePow(makeVariable(), makeConstantDouble((double)i));
665
     monomials  = addElement(monomials, monomial);
666
     fprintf(stderr, "pobyso_create_canonical_monomials_base: %u\n", i);
667
  }
668
  if (monomials == NULL)
669
  {
670
    pobyso_error_message("pobyso_create_canonical_monomial_base",
671
                        "CHAIN_CREATION_ERROR",
672
                        "Could not create the monomials chain");
673
    return(NULL);
674
  }
675
  return(monomials);
676
} /* End pobyso_create_canonical_monomials_base. */
677

678
chain*
679
pobyso_create_chain_from_int_array(int* intArray,
680
                                    const unsigned int arrayLength)
681
{
682
  int i = 0;
683
  chain *newChain = NULL;
684
  int *currentInt;
685

686
  if (arrayLength == 0) return(NULL);
687
  if (intArray == NULL)
688
  {
689
    pobyso_error_message("pobyso_create_chain_from_int_array",
690
                        "NULL_POINTER_ARGUMENT",
691
                        "The array is a NULL pointer");
692
    return(NULL);
693
  }
694
  for (i = arrayLength - 1 ; i >= 0 ; i--)
695
  {
696
    currentInt = malloc(sizeof(int));
697
    if (currentInt == NULL)
698
    {
699
      pobyso_error_message("pobyso_create_chain_from_int_array",
700
                          "MEMORY_ALLOCATION_ERROR",
701
                          "Could not allocate one of the integers");
702
      freeChain(newChain, free);
703
      return(NULL);
704
    }
705
    *currentInt = intArray[i];
706
    newChain = addElement(newChain, currentInt);
707
  }
708
  return(newChain);
709
} // End pobyso_create_chain_from_int_array. */
710

711
chain*
712
pobyso_create_chain_from_unsigned_int_array(unsigned int* intArray,
713
                                        const unsigned int arrayLength)
714
{
715
  int i = 0;
716
  chain *newChain = NULL;
717
  unsigned int *currentInt;
718

719
  /* Argument checking. */
720
  if (arrayLength == 0) return(NULL);
721
  if (intArray == NULL)
722
  {
723
    pobyso_error_message("pobyso_create_chain_from_unsigned_int_array",
724
                        "NULL_POINTER_ARGUMENT",
725
                        "The array is a NULL pointer");
726
    return(NULL);
727
  }
728
  for (i = arrayLength - 1 ; i >= 0 ; i--)
729
  {
730
    currentInt = malloc(sizeof(unsigned int));
731
    if (currentInt == NULL)
732
    {
733
      pobyso_error_message("pobyso_create_chain_from_unsigned_int_array",
734
                          "MEMORY_ALLOCATION_ERROR",
735
                          "Could not allocate one of the integers");
736
      freeChain(newChain, free);
737
      return(NULL);
738
    }
739
    *currentInt = intArray[i];
740
    newChain = addElement(newChain, currentInt);
741
  }
742
  return(newChain);
743
} // End pobyso_create_chain_from_unsigned_int_array. */
744

745
node*
746
pobyso_differentiate(node *functionNode)
747
{
748
  /* Argument checking. */
749
  node *differentialNode;
750
  if (functionNode == NULL)
751
  {
752
    pobyso_error_message("pobyso_differentiate",
753
                        "NULL_POINTER_ARGUMENT",
754
                        "The function to differentiate is a NULL pointer");
755
    return(NULL);
756
  }
757
  differentialNode = differentiate(functionNode);
758
  if (differentialNode == NULL)
759
  {
760
    pobyso_error_message("pobyso_differentiate",
761
                        "INTERNAL ERROR",
762
                        "Sollya could not differentiate the function");
763
  }
764
  return(differentialNode);
765
} // End pobyso_differentiate
766

767

768
int
769
pobyso_dirty_infnorm(mpfr_t infNorm,
770
                      node *functionNode,
771
                      mpfr_t lowerBound,
772
                      mpfr_t upperBound,
773
                      mp_prec_t precision)
774
{
775
  int functionCallResult;
776
  /* Arguments checking. */
777
  if (functionNode == NULL)
778
  {
779
    pobyso_error_message("pobyso_dirty_infnorm",
780
                        "NULL_POINTER_ARGUMENT",
781
                        "The function to compute is a NULL pointer");
782
    return(1);
783
  }
784
  if (mpfr_cmp(lowerBound, upperBound) > 0)
785
  {
786
    pobyso_error_message("pobyso_dirty_infnorm",
787
                        "INCOHERENT_INPUT_DATA",
788
                        "The lower bond is greater than the upper bound");
789
    return(1);
790
  }
791
  /* Particular cases. */
792
  if (mpfr_cmp(lowerBound, upperBound) == 0)
793
  {
794
    functionCallResult = pobyso_evaluate_faithful(infNorm,
795
                                                  functionNode,
796
                                                  lowerBound,
797
                                                  precision);
798
    return(functionCallResult);
799
  }
800
  if (isConstant(functionNode))
801
  {
802
    functionCallResult = pobyso_evaluate_faithful(infNorm,
803
                                                  functionNode,
804
                                                  lowerBound,
805
                                                  precision);
806
    if (!functionCallResult)
807
    {
808
      mpfr_abs(infNorm, infNorm, MPFR_RNDN);
809
    }
810
    return(functionCallResult);
811
  }
812
  uncertifiedInfnorm(infNorm,
813
                      functionNode,
814
                      lowerBound,
815
                      upperBound,
816
                      POBYSO_DEFAULT_POINTS,
817
                      precision);
818
  return(0);
819
} /* End pobyso_dirty_infnorm. */
820

821
int
822
pobyso_evaluate_faithful(mpfr_t faithfulEvaluation,
823
                          node *nodeToEvaluate,
824
                          mpfr_t argument,
825
                          mpfr_prec_t precision)
826
{
827
  /* Check input arguments. */
828
  if (nodeToEvaluate == NULL)
829
  {
830
    pobyso_error_message("pobyso_evaluate_faithful",
831
                        "NULL_POINTER_ARGUMENT",
832
                        "nodeToEvaluate is a NULL pointer");
833
    return(1);
834
  }
835
  evaluateFaithful(faithfulEvaluation,
836
                   nodeToEvaluate,
837
                   argument,
838
                   precision);
839
  return(0);
840
} /* End pobyso_evaluate_faithfull. */
841

842
chain*
843
pobyso_find_zeros(node *function,
844
                  mpfr_t *lower_bound,
845
                  mpfr_t *upper_bound)
846
{
847
  mp_prec_t currentPrecision;
848
  mpfr_t currentDiameter;
849
  rangetype bounds;
850

851
  currentPrecision = getToolPrecision();
852
  mpfr_init2(currentDiameter, currentPrecision);
853

854
  bounds.a = lower_bound;
855
  bounds.b = upper_bound;
856

857
  if (bounds.a == NULL || bounds.b == NULL)
858
  {
859
    pobyso_error_message("pobyso_find_zeros",
860
                        "MEMORY_ALLOCATION_ERROR",
861
                        "Could not allocate one of the bounds");
862
    return(NULL);
863
  }
864
  return(findZerosFunction(function,
865
                            bounds,
866
                            currentPrecision,
867
                            currentDiameter));
868
} /* End pobyso_find_zeros. */
869

870
void
871
pobyso_free_chain_of_nodes(chain *theChainOfNodes)
872
{
873
  node *currentNode           = NULL;
874
  chain *currentChainElement  = NULL;
875
  chain *nextChainElement     = NULL;
876

877
  nextChainElement = theChainOfNodes;
878

879
  while(nextChainElement != NULL)
880
  {
881
    currentChainElement = nextChainElement;
882
    currentNode = (node*)(currentChainElement->value);
883
    nextChainElement = nextChainElement->next;
884
    free_memory(currentNode);
885
    free((void*)(currentChainElement));
886
  }
887
} /* End pobyso_free_chain_of_nodes. */
888

889
void
890
pobyso_free_range(rangetype range)
891
{
892

893
  mpfr_clear(*(range.a));
894
  mpfr_clear(*(range.b));
895
  free(range.a);
896
  free(range.b);
897
} /* End pobyso_free_range. */
898

899
node*
900
pobyso_fp_minimax_canonical_monomials_base(node *function,
901
                                      int degree,
902
                                      chain *formats,
903
                                      chain *points,
904
                                      mpfr_t lowerBound,
905
                                      mpfr_t upperBound,
906
                                      int fpFixedArg,
907
                                      int absRel,
908
                                      node *constPart,
909
                                      node *minimax)
910
{
911
  return(NULL);
912
} /* End pobyso_fp_minimax_canonical_monomials_base. */
913

914
node*
915
pobyso_parse_function(char *functionString,
916
                      char *freeVariableNameString)
917
{
918
  if (functionString == NULL || freeVariableNameString == NULL)
919
  {
920
    pobyso_error_message("pobyso_parse_function",
921
                        "NULL_POINTER_ARGUMENT",
922
                        "One of the arguments is a NULL pointer");
923
    return(NULL);
924
  }
925
  return(parseString(functionString));
926

927
} /* End pobyso_parse_function */
928

929
node*
930
pobyso_remez_approx_canonical_monomials_base_for_error(node *functionNode,
931
                                                  unsigned int mode,
932
                                                  mpfr_t lowerBound,
933
                                                  mpfr_t upperBound,
934
                                                  mpfr_t eps)
935
{
936
  node *weight              = NULL;
937
  node *bestApproxPolyNode  = NULL;
938
  node *bestApproxHorner    = NULL;
939
  node *errorNode           = NULL;
940
  rangetype degreeRange;
941
  mpfr_t quality;
942
  mpfr_t currentError;
943
  unsigned int degree;
944

945
  /* Check the parameters. */
946
  if (functionNode == NULL)
947
  {
948
    pobyso_error_message("remezApproxCanonicalMonomialsBaseForError",
949
                        "NULL_POINTER_ARGUMENT",
950
                        "functionNode is a NULL pointer");
951
    return(NULL);
952
  }
953
  if (mpfr_cmp(lowerBound, upperBound) >= 0)
954
  {
955
    pobyso_error_message("remezApproxCanonicalMonomialsBaseForError",
956
                        "INCOHERENT_INPUT_DATA",
957
                        "the lower_bound >= upper_bound");
958
    return(NULL);
959
  }
960
  /* Set the weight. */
961
  if (mode == POBYSO_ABSOLUTE)
962
  {
963
    /* Set the weight to 1 for the ABSOLUTE_MODE. */
964
    weight = makeConstantDouble(1.0);
965
  }
966
  else
967
  {
968
    if (mode == POBYSO_RELATIVE)
969
    {
970
      pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
971
                          "NOT_IMPLEMENTED",
972
                          "the search for relative error is not implemented yet");
973
      return(NULL);
974
    }
975
    else
976
    {
977
      pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
978
                          "INCOHERENT_INPUT_DATA",
979
                          "the mode is node of POBYSO_ABOLUTE or POBYSO_RELATIVE");
980
      return(NULL);
981
    }
982
  }
983
  //fprintf(stderr, "\n\n\n******* I'm here! ********\n\n\n");
984
  degreeRange = guessDegree(functionNode,
985
                            weight,
986
                            lowerBound,
987
                            upperBound,
988
                            eps,
989
                            POBYSO_GUESS_DEGREE_BOUND);
990
  degree = mpfr_get_ui(*(degreeRange.a), MPFR_RNDN);
991
  //fprintf(stderr, "\n\n\n******* I'm back! ********\n\n\n");
992
  fprintf(stderr, "Guessed degree: ");
993
  mpfr_out_str(stderr, 10, 17, *(degreeRange.a), MPFR_RNDN);
994
  fprintf(stderr, " - as int: %u\n", degree);
995
  /* Reduce the degree by 1 in the foolish hope it could work. */
996
  if (degree > 0) degree--;
997
  /* Both elements of degreeRange where "inited" within guessDegree. */
998
  mpfr_clear(*(degreeRange.a));
999
  mpfr_clear(*(degreeRange.b));
1000
  free(degreeRange.a);
1001
  free(degreeRange.b);
1002
  /* Mimic the default behavior of interactive Sollya. */
1003
  mpfr_init(quality);
1004
  mpfr_set_d(quality, 1e-5, MPFR_RNDN);
1005
  mpfr_init2(currentError, getToolPrecision());
1006
  mpfr_set_inf(currentError,1);
1007

1008
  /* Try to refine the initial guess: loop with increasing degrees until
1009
   * we find a satisfactory one. */
1010
  while(mpfr_cmp(currentError, eps) > 0)
1011
  {
1012
    /* Get rid of the previous polynomial, if any. */
1013
    if (bestApproxPolyNode != NULL)
1014
    {
1015
      free_memory(bestApproxPolyNode);
1016
    }
1017
    fprintf(stderr, "Degree: %u\n", degree);
1018
    fprintf(stderr, "Calling pobyso_remez_canonical_monomials_base...\n");
1019
    /* Try to find a polynomial with the guessed degree. */
1020
    bestApproxPolyNode = pobyso_remez_canonical_monomials_base(functionNode,
1021
                                                            weight,
1022
                                                            degree,
1023
                                                            lowerBound,
1024
                                                            upperBound,
1025
                                                            quality);
1026

1027
    if (bestApproxPolyNode == NULL)
1028
    {
1029
      pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
1030
                          "INTERNAL_ERROR",
1031
                          "could not compute the bestApproxPolyNode");
1032
      mpfr_clear(currentError);
1033
      mpfr_clear(quality);
1034
      return(NULL);
1035
    }
1036

1037
    setDisplayMode(DISPLAY_MODE_DECIMAL);
1038
    fprintTree(stderr, bestApproxPolyNode);
1039
    fprintf(stderr, "\n\n");
1040

1041
    errorNode = makeSub(copyTree(functionNode), copyTree(bestApproxPolyNode));
1042
    /* Check the error with the computed polynomial. */
1043
    uncertifiedInfnorm(currentError,
1044
                        errorNode,
1045
                        lowerBound,
1046
                        upperBound,
1047
                        POBYSO_INF_NORM_NUM_POINTS,
1048
                        getToolPrecision());
1049
    fprintf(stderr, "Inf norm: ");
1050
    mpfr_out_str(stderr, 10, 17, currentError, MPFR_RNDN);
1051
    fprintf(stderr, "\n\n");
1052
    /* Free the errorNode but not the bestApproxPolyNode (we need it if
1053
     * we exit the loop at the next iteration). */
1054
    free_memory(errorNode);
1055
    degree++;
1056
  }
1057
  /* Use an intermediate variable, since horner() creates a new node
1058
   * and does not reorder the argument "in place". This allows for the memory
1059
   * reclaim of bestApproxHorner.
1060
   */
1061
  bestApproxHorner = horner(bestApproxPolyNode);
1062
  free_memory(bestApproxPolyNode);
1063
  mpfr_clear(currentError);
1064
  mpfr_clear(quality);
1065
  free_memory(weight);
1066
  return(bestApproxHorner);
1067
} /* End pobyso_remez_approx_canonical_monomials_base_for_error */
1068

1069
node*
1070
pobyso_remez_canonical_monomials_base(node *function,
1071
                                     node *weight,
1072
                                     unsigned int degree,
1073
                                     mpfr_t lowerBound,
1074
                                     mpfr_t upperBound,
1075
                                     mpfr_t quality)
1076
{
1077
  node  *bestApproxPoly = NULL;
1078
  chain *monomials      = NULL;
1079
  chain *curMonomial    = NULL;
1080

1081
  mpfr_t satisfying_error;
1082
  mpfr_t target_error;
1083

1084
  /* Argument checking */
1085
  /* Function tree. */
1086
  if (function == NULL)
1087
  {
1088
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
1089
                        "NULL_POINTER_ARGUMENT",
1090
                        "the \"function\" argument is a NULL pointer");
1091
    return(NULL);
1092
  }
1093
  if (weight == NULL)
1094
  {
1095
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
1096
                        "NULL_POINTER_ARGUMENT",
1097
                        "the \"weight\" argument is a NULL pointer");
1098
    return(NULL);
1099
  }
1100
  /* Check the bounds. */
1101
  if (mpfr_cmp(lowerBound, upperBound) >= 0)
1102
  {
1103
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
1104
                        "INCOHERENT_IMPUT_DATA",
1105
                        "the lower_bound >= upper_bound");
1106
    return(NULL);
1107
  }
1108
  /* The quality must be a non null positive number. */
1109
  if (mpfr_sgn(quality) <= 0)
1110
  {
1111
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
1112
                        "INCOHERENT_INPUT_DATA",
1113
                        "the quality <= 0");
1114
  }
1115
  /* End argument checking. */
1116
  /* Create the monomials nodes chains. */
1117
  monomials = pobyso_create_canonical_monomials_base(degree);
1118
  fprintf(stderr, "monomials chain length = %d\n", lengthChain(monomials));
1119
  if (monomials == NULL || (lengthChain(monomials) != degree + 1))
1120
  {
1121
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
1122
                        "CHAIN_CREATION_ERROR",
1123
                        "could not create the monomials chain");
1124
    return(NULL);
1125
  }
1126
  curMonomial = monomials;
1127

1128
  while (curMonomial != NULL)
1129
  {
1130
    fprintf(stderr, "monomial tree: ");
1131
    //mpfr_out_str(stderr, 10, 17, *((mpfr_t*)((node*)(curMonomial->value))->value), MPFR_RNDN);
1132
    fprintTree(stderr, (node*)(curMonomial->value));
1133
    fprintf(stderr, "\n");
1134
    curMonomial = curMonomial->next;
1135
  }
1136

1137
  /* Deal with NULL weight. */
1138
  if (weight == NULL)
1139
  {
1140
    weight = makeConstantDouble(1.0);
1141
  }
1142
  /* Compute the best polynomial with the required quality.
1143
     The behavior is as if satisfying error and target_error had
1144
     not been used.*/
1145
  mpfr_init(satisfying_error);
1146
  mpfr_init(target_error);
1147
  mpfr_set_str(satisfying_error, "0", 10, MPFR_RNDN);
1148
  mpfr_set_inf(target_error, 1);
1149

1150

1151
  fprintf(stderr, "satisfying_error: ");
1152
  mpfr_out_str(stderr, 10, 17, satisfying_error, MPFR_RNDN);
1153
  fprintf(stderr, ".\n");
1154
  fprintf(stderr, "target_error: ");
1155
  mpfr_out_str(stderr, 10, 17, target_error,MPFR_RNDN);
1156
  fprintf(stderr, ".\n");
1157

1158
  fprintf(stderr,
1159
          "current precision: %li\n", getToolPrecision());
1160
  /* Call the Sollya function. */
1161
  bestApproxPoly = remez(function,
1162
                          weight,
1163
                          monomials,
1164
                          lowerBound,
1165
                          upperBound,
1166
                          quality,
1167
                          satisfying_error,
1168
                          target_error,
1169
                          getToolPrecision());
1170

1171
  mpfr_clear(satisfying_error);
1172
  mpfr_clear(target_error);
1173
  pobyso_free_chain_of_nodes(monomials);
1174

1175
  return(bestApproxPoly);
1176
} /* End pobyso_remez_canonical_monomials_base. */
1177

1178
#endif
1179

    
1180
void
1181
pobyso_error_message(char *functionName, char *messageName, char* message)
1182
{
1183
  fprintf(stderr, "?%s: %s.\n%s.\n", functionName, messageName, message);
1184
} /* End pobyso_error_message */