Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (19,92 ko)

1 26 storres
/** @file pobyso.c
2 26 storres
 * Name & purpose
3 26 storres
 *
4 26 storres
 * @author S.T.
5 26 storres
 * @date 2011-10-12
6 26 storres
 *
7 27 storres
 *
8 26 storres
 */
9 50 storres
10 26 storres
/******************************************************************************/
11 26 storres
/* Headers, applying the "particular to general" convention.*/
12 26 storres
13 26 storres
#include "pobyso.h"
14 26 storres
15 26 storres
/* includes of local headers */
16 26 storres
17 26 storres
/* includes of project headers */
18 26 storres
19 26 storres
/* includes of system headers */
20 26 storres
21 26 storres
/* Other declarations */
22 26 storres
23 26 storres
/* Internal prototypes */
24 26 storres
void
25 26 storres
pobyso_error_message(char *functionName, char *messageName, char* message);
26 26 storres
/* Types, constants and macros definitions */
27 26 storres
28 26 storres
/* Global variables */
29 26 storres
30 26 storres
/* Functions */
31 127 storres
32 127 storres
/* @see pobyso.h#pobyso_autprint */
33 26 storres
void
34 26 storres
pobyso_autoprint(sollya_obj_t solObj, ...)
35 26 storres
{
36 26 storres
  va_list va;
37 26 storres
  va_start(va, solObj);
38 26 storres
  sollya_lib_v_autoprint(solObj, va);
39 26 storres
  va_end(va);
40 26 storres
} /* End pobyso_autoprint. */
41 26 storres
42 127 storres
/* @see pobyso.h#pobyso_parse_string*/
43 26 storres
sollya_obj_t
44 26 storres
pobyso_parse_string(const char* expression)
45 26 storres
{
46 127 storres
  int expressionLength;
47 127 storres
  char *expressionWithSemiCo;
48 127 storres
  sollya_obj_t expressionSa;
49 127 storres
  /* Arguments check. */
50 26 storres
  if (expression == NULL)
51 26 storres
  {
52 26 storres
    pobyso_error_message("pobyso_parse_string",
53 26 storres
                        "NULL_POINTER_ARGUMENT",
54 26 storres
                        "The expression is a NULL pointer");
55 127 storres
    return(sollya_lib_error());
56 26 storres
  }
57 127 storres
  expressionLength = strlen(expression);
58 127 storres
  if (expressionLength == 0)
59 127 storres
  {
60 127 storres
    pobyso_error_message("pobyso_parse_string",
61 127 storres
                        "EMPTY_STRING_ARGUMENT",
62 127 storres
                        "The expression is an empty string");
63 127 storres
  }
64 127 storres
  /* If the final ";" has been forgotten. */
65 127 storres
  if (expression[expressionLength-1] != ';')
66 127 storres
  {
67 127 storres
    expressionWithSemiCo = calloc(expressionLength + 2, sizeof(char));
68 127 storres
    if (expressionWithSemiCo == NULL)
69 127 storres
    {
70 127 storres
      pobyso_error_message("pobyso_parse_string",
71 127 storres
                            "MEMORY_ALLOCATION_ERROR",
72 127 storres
                            "Could not allocate the expression string");
73 127 storres
      return(sollya_lib_error());
74 127 storres
    }
75 127 storres
    expressionWithSemiCo = strcat(expressionWithSemiCo, expression);
76 127 storres
    expressionWithSemiCo = strcat(expressionWithSemiCo, ";");
77 127 storres
    expressionSa = sollya_lib_parse_string(expressionWithSemiCo);
78 127 storres
    free(expressionWithSemiCo);
79 127 storres
    return(expressionSa);
80 127 storres
  } /* End ";" forgotten */
81 127 storres
  else
82 127 storres
  {
83 127 storres
    return(sollya_lib_parse_string(expression));
84 127 storres
  }
85 26 storres
} /* pobyso_parse_string */
86 26 storres
87 26 storres
void
88 26 storres
pobyso_set_verbosity_off(sollya_obj_t* currentVerbosityLevel)
89 26 storres
{
90 26 storres
  sollya_obj_t verbosityLevelZero;
91 26 storres
  if (currentVerbosityLevel != NULL)
92 26 storres
  {
93 26 storres
     *currentVerbosityLevel = sollya_lib_get_verbosity();
94 26 storres
  }
95 26 storres
  verbosityLevelZero = sollya_lib_constant_from_int(0);
96 26 storres
  sollya_lib_set_verbosity(verbosityLevelZero);
97 26 storres
  sollya_lib_clear_obj(verbosityLevelZero);
98 26 storres
} /* End of pobyso_set_verbosity_off. */
99 26 storres
100 26 storres
void
101 26 storres
pobyso_set_verbosity_to(sollya_obj_t newVerbosityLevel)
102 26 storres
{
103 26 storres
  if (newVerbosityLevel == NULL)
104 26 storres
  {
105 26 storres
    pobyso_error_message("pobyso_set_verbosity_to",
106 26 storres
                        "NULL_POINTER_ARGUMENT",
107 26 storres
                        "The new verbosity level is a NULL pointer");
108 26 storres
    return;
109 26 storres
  }
110 26 storres
  sollya_lib_set_verbosity(newVerbosityLevel);
111 26 storres
} /* End of pobyso_set_verbosity_to. */
112 26 storres
113 26 storres
/* Attic from the sollya_lib < 4. */
114 26 storres
#if 0
115 26 storres
chain*
116 26 storres
pobyso_create_canonical_monomials_base(const unsigned int degree)
117 26 storres
{
118 26 storres
  int i    = 0;
119 26 storres
  chain *monomials  = NULL;
120 26 storres
  node  *monomial   = NULL;
121 26 storres

122 26 storres
  for(i = degree ; i >= 0  ; i--)
123 26 storres
  {
124 26 storres
     monomial   = makePow(makeVariable(), makeConstantDouble((double)i));
125 26 storres
     monomials  = addElement(monomials, monomial);
126 26 storres
     fprintf(stderr, "pobyso_create_canonical_monomials_base: %u\n", i);
127 26 storres
  }
128 26 storres
  if (monomials == NULL)
129 26 storres
  {
130 26 storres
    pobyso_error_message("pobyso_create_canonical_monomial_base",
131 26 storres
                        "CHAIN_CREATION_ERROR",
132 26 storres
                        "Could not create the monomials chain");
133 26 storres
    return(NULL);
134 26 storres
  }
135 26 storres
  return(monomials);
136 26 storres
} /* End pobyso_create_canonical_monomials_base. */
137 26 storres

138 26 storres
chain*
139 26 storres
pobyso_create_chain_from_int_array(int* intArray,
140 26 storres
                                    const unsigned int arrayLength)
141 26 storres
{
142 26 storres
  int i = 0;
143 26 storres
  chain *newChain = NULL;
144 26 storres
  int *currentInt;
145 26 storres

146 26 storres
  if (arrayLength == 0) return(NULL);
147 26 storres
  if (intArray == NULL)
148 26 storres
  {
149 26 storres
    pobyso_error_message("pobyso_create_chain_from_int_array",
150 26 storres
                        "NULL_POINTER_ARGUMENT",
151 26 storres
                        "The array is a NULL pointer");
152 26 storres
    return(NULL);
153 26 storres
  }
154 26 storres
  for (i = arrayLength - 1 ; i >= 0 ; i--)
155 26 storres
  {
156 26 storres
    currentInt = malloc(sizeof(int));
157 26 storres
    if (currentInt == NULL)
158 26 storres
    {
159 26 storres
      pobyso_error_message("pobyso_create_chain_from_int_array",
160 26 storres
                          "MEMORY_ALLOCATION_ERROR",
161 26 storres
                          "Could not allocate one of the integers");
162 26 storres
      freeChain(newChain, free);
163 26 storres
      return(NULL);
164 26 storres
    }
165 26 storres
    *currentInt = intArray[i];
166 26 storres
    newChain = addElement(newChain, currentInt);
167 26 storres
  }
168 26 storres
  return(newChain);
169 26 storres
} // End pobyso_create_chain_from_int_array. */
170 26 storres

171 26 storres
chain*
172 26 storres
pobyso_create_chain_from_unsigned_int_array(unsigned int* intArray,
173 26 storres
                                        const unsigned int arrayLength)
174 26 storres
{
175 26 storres
  int i = 0;
176 26 storres
  chain *newChain = NULL;
177 26 storres
  unsigned int *currentInt;
178 26 storres

179 26 storres
  /* Argument checking. */
180 26 storres
  if (arrayLength == 0) return(NULL);
181 26 storres
  if (intArray == NULL)
182 26 storres
  {
183 26 storres
    pobyso_error_message("pobyso_create_chain_from_unsigned_int_array",
184 26 storres
                        "NULL_POINTER_ARGUMENT",
185 26 storres
                        "The array is a NULL pointer");
186 26 storres
    return(NULL);
187 26 storres
  }
188 26 storres
  for (i = arrayLength - 1 ; i >= 0 ; i--)
189 26 storres
  {
190 26 storres
    currentInt = malloc(sizeof(unsigned int));
191 26 storres
    if (currentInt == NULL)
192 26 storres
    {
193 26 storres
      pobyso_error_message("pobyso_create_chain_from_unsigned_int_array",
194 26 storres
                          "MEMORY_ALLOCATION_ERROR",
195 26 storres
                          "Could not allocate one of the integers");
196 26 storres
      freeChain(newChain, free);
197 26 storres
      return(NULL);
198 26 storres
    }
199 26 storres
    *currentInt = intArray[i];
200 26 storres
    newChain = addElement(newChain, currentInt);
201 26 storres
  }
202 26 storres
  return(newChain);
203 26 storres
} // End pobyso_create_chain_from_unsigned_int_array. */
204 26 storres

205 26 storres
node*
206 26 storres
pobyso_differentiate(node *functionNode)
207 26 storres
{
208 26 storres
  /* Argument checking. */
209 26 storres
  node *differentialNode;
210 26 storres
  if (functionNode == NULL)
211 26 storres
  {
212 26 storres
    pobyso_error_message("pobyso_differentiate",
213 26 storres
                        "NULL_POINTER_ARGUMENT",
214 26 storres
                        "The function to differentiate is a NULL pointer");
215 26 storres
    return(NULL);
216 26 storres
  }
217 26 storres
  differentialNode = differentiate(functionNode);
218 26 storres
  if (differentialNode == NULL)
219 26 storres
  {
220 26 storres
    pobyso_error_message("pobyso_differentiate",
221 26 storres
                        "INTERNAL ERROR",
222 26 storres
                        "Sollya could not differentiate the function");
223 26 storres
  }
224 26 storres
  return(differentialNode);
225 26 storres
} // End pobyso_differentiate
226 26 storres

227 26 storres

228 26 storres
int
229 26 storres
pobyso_dirty_infnorm(mpfr_t infNorm,
230 26 storres
                      node *functionNode,
231 26 storres
                      mpfr_t lowerBound,
232 26 storres
                      mpfr_t upperBound,
233 26 storres
                      mp_prec_t precision)
234 26 storres
{
235 26 storres
  int functionCallResult;
236 26 storres
  /* Arguments checking. */
237 26 storres
  if (functionNode == NULL)
238 26 storres
  {
239 26 storres
    pobyso_error_message("pobyso_dirty_infnorm",
240 26 storres
                        "NULL_POINTER_ARGUMENT",
241 26 storres
                        "The function to compute is a NULL pointer");
242 26 storres
    return(1);
243 26 storres
  }
244 26 storres
  if (mpfr_cmp(lowerBound, upperBound) > 0)
245 26 storres
  {
246 26 storres
    pobyso_error_message("pobyso_dirty_infnorm",
247 26 storres
                        "INCOHERENT_INPUT_DATA",
248 26 storres
                        "The lower bond is greater than the upper bound");
249 26 storres
    return(1);
250 26 storres
  }
251 26 storres
  /* Particular cases. */
252 26 storres
  if (mpfr_cmp(lowerBound, upperBound) == 0)
253 26 storres
  {
254 26 storres
    functionCallResult = pobyso_evaluate_faithful(infNorm,
255 26 storres
                                                  functionNode,
256 26 storres
                                                  lowerBound,
257 26 storres
                                                  precision);
258 26 storres
    return(functionCallResult);
259 26 storres
  }
260 26 storres
  if (isConstant(functionNode))
261 26 storres
  {
262 26 storres
    functionCallResult = pobyso_evaluate_faithful(infNorm,
263 26 storres
                                                  functionNode,
264 26 storres
                                                  lowerBound,
265 26 storres
                                                  precision);
266 26 storres
    if (!functionCallResult)
267 26 storres
    {
268 26 storres
      mpfr_abs(infNorm, infNorm, MPFR_RNDN);
269 26 storres
    }
270 26 storres
    return(functionCallResult);
271 26 storres
  }
272 26 storres
  uncertifiedInfnorm(infNorm,
273 26 storres
                      functionNode,
274 26 storres
                      lowerBound,
275 26 storres
                      upperBound,
276 26 storres
                      POBYSO_DEFAULT_POINTS,
277 26 storres
                      precision);
278 26 storres
  return(0);
279 26 storres
} /* End pobyso_dirty_infnorm. */
280 26 storres

281 26 storres
int
282 26 storres
pobyso_evaluate_faithful(mpfr_t faithfulEvaluation,
283 26 storres
                          node *nodeToEvaluate,
284 26 storres
                          mpfr_t argument,
285 26 storres
                          mpfr_prec_t precision)
286 26 storres
{
287 26 storres
  /* Check input arguments. */
288 26 storres
  if (nodeToEvaluate == NULL)
289 26 storres
  {
290 26 storres
    pobyso_error_message("pobyso_evaluate_faithful",
291 26 storres
                        "NULL_POINTER_ARGUMENT",
292 26 storres
                        "nodeToEvaluate is a NULL pointer");
293 26 storres
    return(1);
294 26 storres
  }
295 26 storres
  evaluateFaithful(faithfulEvaluation,
296 26 storres
                   nodeToEvaluate,
297 26 storres
                   argument,
298 26 storres
                   precision);
299 26 storres
  return(0);
300 26 storres
} /* End pobyso_evaluate_faithfull. */
301 26 storres

302 26 storres
chain*
303 26 storres
pobyso_find_zeros(node *function,
304 26 storres
                  mpfr_t *lower_bound,
305 26 storres
                  mpfr_t *upper_bound)
306 26 storres
{
307 26 storres
  mp_prec_t currentPrecision;
308 26 storres
  mpfr_t currentDiameter;
309 26 storres
  rangetype bounds;
310 26 storres

311 26 storres
  currentPrecision = getToolPrecision();
312 26 storres
  mpfr_init2(currentDiameter, currentPrecision);
313 26 storres

314 26 storres
  bounds.a = lower_bound;
315 26 storres
  bounds.b = upper_bound;
316 26 storres

317 26 storres
  if (bounds.a == NULL || bounds.b == NULL)
318 26 storres
  {
319 26 storres
    pobyso_error_message("pobyso_find_zeros",
320 26 storres
                        "MEMORY_ALLOCATION_ERROR",
321 26 storres
                        "Could not allocate one of the bounds");
322 26 storres
    return(NULL);
323 26 storres
  }
324 26 storres
  return(findZerosFunction(function,
325 26 storres
                            bounds,
326 26 storres
                            currentPrecision,
327 26 storres
                            currentDiameter));
328 26 storres
} /* End pobyso_find_zeros. */
329 26 storres

330 26 storres
void
331 26 storres
pobyso_free_chain_of_nodes(chain *theChainOfNodes)
332 26 storres
{
333 26 storres
  node *currentNode           = NULL;
334 26 storres
  chain *currentChainElement  = NULL;
335 26 storres
  chain *nextChainElement     = NULL;
336 26 storres

337 26 storres
  nextChainElement = theChainOfNodes;
338 26 storres

339 26 storres
  while(nextChainElement != NULL)
340 26 storres
  {
341 26 storres
    currentChainElement = nextChainElement;
342 26 storres
    currentNode = (node*)(currentChainElement->value);
343 26 storres
    nextChainElement = nextChainElement->next;
344 26 storres
    free_memory(currentNode);
345 26 storres
    free((void*)(currentChainElement));
346 26 storres
  }
347 26 storres
} /* End pobyso_free_chain_of_nodes. */
348 26 storres

349 26 storres
void
350 26 storres
pobyso_free_range(rangetype range)
351 26 storres
{
352 26 storres

353 26 storres
  mpfr_clear(*(range.a));
354 26 storres
  mpfr_clear(*(range.b));
355 26 storres
  free(range.a);
356 26 storres
  free(range.b);
357 26 storres
} /* End pobyso_free_range. */
358 26 storres

359 26 storres
node*
360 26 storres
pobyso_fp_minimax_canonical_monomials_base(node *function,
361 26 storres
                                      int degree,
362 26 storres
                                      chain *formats,
363 26 storres
                                      chain *points,
364 26 storres
                                      mpfr_t lowerBound,
365 26 storres
                                      mpfr_t upperBound,
366 26 storres
                                      int fpFixedArg,
367 26 storres
                                      int absRel,
368 26 storres
                                      node *constPart,
369 26 storres
                                      node *minimax)
370 26 storres
{
371 26 storres
  return(NULL);
372 26 storres
} /* End pobyso_fp_minimax_canonical_monomials_base. */
373 26 storres

374 26 storres
node*
375 26 storres
pobyso_parse_function(char *functionString,
376 26 storres
                      char *freeVariableNameString)
377 26 storres
{
378 26 storres
  if (functionString == NULL || freeVariableNameString == NULL)
379 26 storres
  {
380 26 storres
    pobyso_error_message("pobyso_parse_function",
381 26 storres
                        "NULL_POINTER_ARGUMENT",
382 26 storres
                        "One of the arguments is a NULL pointer");
383 26 storres
    return(NULL);
384 26 storres
  }
385 26 storres
  return(parseString(functionString));
386 26 storres

387 26 storres
} /* End pobyso_parse_function */
388 26 storres

389 26 storres
node*
390 26 storres
pobyso_remez_approx_canonical_monomials_base_for_error(node *functionNode,
391 26 storres
                                                  unsigned int mode,
392 26 storres
                                                  mpfr_t lowerBound,
393 26 storres
                                                  mpfr_t upperBound,
394 26 storres
                                                  mpfr_t eps)
395 26 storres
{
396 26 storres
  node *weight              = NULL;
397 26 storres
  node *bestApproxPolyNode  = NULL;
398 26 storres
  node *bestApproxHorner    = NULL;
399 26 storres
  node *errorNode           = NULL;
400 26 storres
  rangetype degreeRange;
401 26 storres
  mpfr_t quality;
402 26 storres
  mpfr_t currentError;
403 26 storres
  unsigned int degree;
404 26 storres

405 26 storres
  /* Check the parameters. */
406 26 storres
  if (functionNode == NULL)
407 26 storres
  {
408 26 storres
    pobyso_error_message("remezApproxCanonicalMonomialsBaseForError",
409 26 storres
                        "NULL_POINTER_ARGUMENT",
410 26 storres
                        "functionNode is a NULL pointer");
411 26 storres
    return(NULL);
412 26 storres
  }
413 26 storres
  if (mpfr_cmp(lowerBound, upperBound) >= 0)
414 26 storres
  {
415 26 storres
    pobyso_error_message("remezApproxCanonicalMonomialsBaseForError",
416 26 storres
                        "INCOHERENT_INPUT_DATA",
417 26 storres
                        "the lower_bound >= upper_bound");
418 26 storres
    return(NULL);
419 26 storres
  }
420 26 storres
  /* Set the weight. */
421 26 storres
  if (mode == POBYSO_ABSOLUTE)
422 26 storres
  {
423 26 storres
    /* Set the weight to 1 for the ABSOLUTE_MODE. */
424 26 storres
    weight = makeConstantDouble(1.0);
425 26 storres
  }
426 26 storres
  else
427 26 storres
  {
428 26 storres
    if (mode == POBYSO_RELATIVE)
429 26 storres
    {
430 26 storres
      pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
431 26 storres
                          "NOT_IMPLEMENTED",
432 26 storres
                          "the search for relative error is not implemented yet");
433 26 storres
      return(NULL);
434 26 storres
    }
435 26 storres
    else
436 26 storres
    {
437 26 storres
      pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
438 26 storres
                          "INCOHERENT_INPUT_DATA",
439 26 storres
                          "the mode is node of POBYSO_ABOLUTE or POBYSO_RELATIVE");
440 26 storres
      return(NULL);
441 26 storres
    }
442 26 storres
  }
443 26 storres
  //fprintf(stderr, "\n\n\n******* I'm here! ********\n\n\n");
444 26 storres
  degreeRange = guessDegree(functionNode,
445 26 storres
                            weight,
446 26 storres
                            lowerBound,
447 26 storres
                            upperBound,
448 26 storres
                            eps,
449 26 storres
                            POBYSO_GUESS_DEGREE_BOUND);
450 26 storres
  degree = mpfr_get_ui(*(degreeRange.a), MPFR_RNDN);
451 26 storres
  //fprintf(stderr, "\n\n\n******* I'm back! ********\n\n\n");
452 26 storres
  fprintf(stderr, "Guessed degree: ");
453 26 storres
  mpfr_out_str(stderr, 10, 17, *(degreeRange.a), MPFR_RNDN);
454 26 storres
  fprintf(stderr, " - as int: %u\n", degree);
455 26 storres
  /* Reduce the degree by 1 in the foolish hope it could work. */
456 26 storres
  if (degree > 0) degree--;
457 26 storres
  /* Both elements of degreeRange where "inited" within guessDegree. */
458 26 storres
  mpfr_clear(*(degreeRange.a));
459 26 storres
  mpfr_clear(*(degreeRange.b));
460 26 storres
  free(degreeRange.a);
461 26 storres
  free(degreeRange.b);
462 26 storres
  /* Mimic the default behavior of interactive Sollya. */
463 26 storres
  mpfr_init(quality);
464 26 storres
  mpfr_set_d(quality, 1e-5, MPFR_RNDN);
465 26 storres
  mpfr_init2(currentError, getToolPrecision());
466 26 storres
  mpfr_set_inf(currentError,1);
467 26 storres

468 26 storres
  /* Try to refine the initial guess: loop with increasing degrees until
469 26 storres
   * we find a satisfactory one. */
470 26 storres
  while(mpfr_cmp(currentError, eps) > 0)
471 26 storres
  {
472 26 storres
    /* Get rid of the previous polynomial, if any. */
473 26 storres
    if (bestApproxPolyNode != NULL)
474 26 storres
    {
475 26 storres
      free_memory(bestApproxPolyNode);
476 26 storres
    }
477 26 storres
    fprintf(stderr, "Degree: %u\n", degree);
478 26 storres
    fprintf(stderr, "Calling pobyso_remez_canonical_monomials_base...\n");
479 26 storres
    /* Try to find a polynomial with the guessed degree. */
480 26 storres
    bestApproxPolyNode = pobyso_remez_canonical_monomials_base(functionNode,
481 26 storres
                                                            weight,
482 26 storres
                                                            degree,
483 26 storres
                                                            lowerBound,
484 26 storres
                                                            upperBound,
485 26 storres
                                                            quality);
486 26 storres

487 26 storres
    if (bestApproxPolyNode == NULL)
488 26 storres
    {
489 26 storres
      pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
490 26 storres
                          "INTERNAL_ERROR",
491 26 storres
                          "could not compute the bestApproxPolyNode");
492 26 storres
      mpfr_clear(currentError);
493 26 storres
      mpfr_clear(quality);
494 26 storres
      return(NULL);
495 26 storres
    }
496 26 storres

497 26 storres
    setDisplayMode(DISPLAY_MODE_DECIMAL);
498 26 storres
    fprintTree(stderr, bestApproxPolyNode);
499 26 storres
    fprintf(stderr, "\n\n");
500 26 storres

501 26 storres
    errorNode = makeSub(copyTree(functionNode), copyTree(bestApproxPolyNode));
502 26 storres
    /* Check the error with the computed polynomial. */
503 26 storres
    uncertifiedInfnorm(currentError,
504 26 storres
                        errorNode,
505 26 storres
                        lowerBound,
506 26 storres
                        upperBound,
507 26 storres
                        POBYSO_INF_NORM_NUM_POINTS,
508 26 storres
                        getToolPrecision());
509 26 storres
    fprintf(stderr, "Inf norm: ");
510 26 storres
    mpfr_out_str(stderr, 10, 17, currentError, MPFR_RNDN);
511 26 storres
    fprintf(stderr, "\n\n");
512 26 storres
    /* Free the errorNode but not the bestApproxPolyNode (we need it if
513 26 storres
     * we exit the loop at the next iteration). */
514 26 storres
    free_memory(errorNode);
515 26 storres
    degree++;
516 26 storres
  }
517 26 storres
  /* Use an intermediate variable, since horner() creates a new node
518 26 storres
   * and does not reorder the argument "in place". This allows for the memory
519 26 storres
   * reclaim of bestApproxHorner.
520 26 storres
   */
521 26 storres
  bestApproxHorner = horner(bestApproxPolyNode);
522 26 storres
  free_memory(bestApproxPolyNode);
523 26 storres
  mpfr_clear(currentError);
524 26 storres
  mpfr_clear(quality);
525 26 storres
  free_memory(weight);
526 26 storres
  return(bestApproxHorner);
527 26 storres
} /* End pobyso_remez_approx_canonical_monomials_base_for_error */
528 26 storres

529 26 storres
node*
530 26 storres
pobyso_remez_canonical_monomials_base(node *function,
531 26 storres
                                     node *weight,
532 26 storres
                                     unsigned int degree,
533 26 storres
                                     mpfr_t lowerBound,
534 26 storres
                                     mpfr_t upperBound,
535 26 storres
                                     mpfr_t quality)
536 26 storres
{
537 26 storres
  node  *bestApproxPoly = NULL;
538 26 storres
  chain *monomials      = NULL;
539 26 storres
  chain *curMonomial    = NULL;
540 26 storres

541 26 storres
  mpfr_t satisfying_error;
542 26 storres
  mpfr_t target_error;
543 26 storres

544 26 storres
  /* Argument checking */
545 26 storres
  /* Function tree. */
546 26 storres
  if (function == NULL)
547 26 storres
  {
548 26 storres
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
549 26 storres
                        "NULL_POINTER_ARGUMENT",
550 26 storres
                        "the \"function\" argument is a NULL pointer");
551 26 storres
    return(NULL);
552 26 storres
  }
553 26 storres
  if (weight == NULL)
554 26 storres
  {
555 26 storres
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
556 26 storres
                        "NULL_POINTER_ARGUMENT",
557 26 storres
                        "the \"weight\" argument is a NULL pointer");
558 26 storres
    return(NULL);
559 26 storres
  }
560 26 storres
  /* Check the bounds. */
561 26 storres
  if (mpfr_cmp(lowerBound, upperBound) >= 0)
562 26 storres
  {
563 26 storres
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
564 26 storres
                        "INCOHERENT_IMPUT_DATA",
565 26 storres
                        "the lower_bound >= upper_bound");
566 26 storres
    return(NULL);
567 26 storres
  }
568 26 storres
  /* The quality must be a non null positive number. */
569 26 storres
  if (mpfr_sgn(quality) <= 0)
570 26 storres
  {
571 26 storres
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
572 26 storres
                        "INCOHERENT_INPUT_DATA",
573 26 storres
                        "the quality <= 0");
574 26 storres
  }
575 26 storres
  /* End argument checking. */
576 26 storres
  /* Create the monomials nodes chains. */
577 26 storres
  monomials = pobyso_create_canonical_monomials_base(degree);
578 26 storres
  fprintf(stderr, "monomials chain length = %d\n", lengthChain(monomials));
579 26 storres
  if (monomials == NULL || (lengthChain(monomials) != degree + 1))
580 26 storres
  {
581 26 storres
    pobyso_error_message("pobyso_remez_canonical_monomials_base",
582 26 storres
                        "CHAIN_CREATION_ERROR",
583 26 storres
                        "could not create the monomials chain");
584 26 storres
    return(NULL);
585 26 storres
  }
586 26 storres
  curMonomial = monomials;
587 26 storres

588 26 storres
  while (curMonomial != NULL)
589 26 storres
  {
590 26 storres
    fprintf(stderr, "monomial tree: ");
591 26 storres
    //mpfr_out_str(stderr, 10, 17, *((mpfr_t*)((node*)(curMonomial->value))->value), MPFR_RNDN);
592 26 storres
    fprintTree(stderr, (node*)(curMonomial->value));
593 26 storres
    fprintf(stderr, "\n");
594 26 storres
    curMonomial = curMonomial->next;
595 26 storres
  }
596 26 storres

597 26 storres
  /* Deal with NULL weight. */
598 26 storres
  if (weight == NULL)
599 26 storres
  {
600 26 storres
    weight = makeConstantDouble(1.0);
601 26 storres
  }
602 26 storres
  /* Compute the best polynomial with the required quality.
603 26 storres
     The behavior is as if satisfying error and target_error had
604 26 storres
     not been used.*/
605 26 storres
  mpfr_init(satisfying_error);
606 26 storres
  mpfr_init(target_error);
607 26 storres
  mpfr_set_str(satisfying_error, "0", 10, MPFR_RNDN);
608 26 storres
  mpfr_set_inf(target_error, 1);
609 26 storres

610 26 storres

611 26 storres
  fprintf(stderr, "satisfying_error: ");
612 26 storres
  mpfr_out_str(stderr, 10, 17, satisfying_error, MPFR_RNDN);
613 26 storres
  fprintf(stderr, ".\n");
614 26 storres
  fprintf(stderr, "target_error: ");
615 26 storres
  mpfr_out_str(stderr, 10, 17, target_error,MPFR_RNDN);
616 26 storres
  fprintf(stderr, ".\n");
617 26 storres

618 26 storres
  fprintf(stderr,
619 26 storres
          "current precision: %li\n", getToolPrecision());
620 26 storres
  /* Call the Sollya function. */
621 26 storres
  bestApproxPoly = remez(function,
622 26 storres
                          weight,
623 26 storres
                          monomials,
624 26 storres
                          lowerBound,
625 26 storres
                          upperBound,
626 26 storres
                          quality,
627 26 storres
                          satisfying_error,
628 26 storres
                          target_error,
629 26 storres
                          getToolPrecision());
630 26 storres

631 26 storres
  mpfr_clear(satisfying_error);
632 26 storres
  mpfr_clear(target_error);
633 26 storres
  pobyso_free_chain_of_nodes(monomials);
634 26 storres

635 26 storres
  return(bestApproxPoly);
636 26 storres
} /* End pobyso_remez_canonical_monomials_base. */
637 26 storres

638 26 storres
#endif
639 26 storres
640 26 storres
void
641 26 storres
pobyso_error_message(char *functionName, char *messageName, char* message)
642 26 storres
{
643 26 storres
  fprintf(stderr, "?%s: %s.\n%s.\n", functionName, messageName, message);
644 26 storres
} /* End pobyso_error_message */