root / pobysoC-4.0 / pobyso.c @ 12
Historique | Voir | Annoter | Télécharger (18,78 ko)
1 | 12 | storres | /** @file pobyso.c
|
---|---|---|---|
2 | 12 | storres | * Name & purpose
|
3 | 12 | storres | *
|
4 | 12 | storres | * @author S.T.
|
5 | 12 | storres | * @date 2011-10-12
|
6 | 12 | storres | *
|
7 | 12 | storres | */
|
8 | 12 | storres | /******************************************************************************/
|
9 | 12 | storres | /* Headers, applying the "particular to general" convention.*/
|
10 | 12 | storres | |
11 | 12 | storres | #include "pobyso.h" |
12 | 12 | storres | |
13 | 12 | storres | /* includes of local headers */
|
14 | 12 | storres | |
15 | 12 | storres | /* includes of project headers */
|
16 | 12 | storres | |
17 | 12 | storres | /* includes of system headers */
|
18 | 12 | storres | |
19 | 12 | storres | /* Other declarations */
|
20 | 12 | storres | |
21 | 12 | storres | /* Internal prototypes */
|
22 | 12 | storres | void
|
23 | 12 | storres | pobyso_error_message(char *functionName, char *messageName, char* message); |
24 | 12 | storres | /* Types, constants and macros definitions */
|
25 | 12 | storres | |
26 | 12 | storres | /* Global variables */
|
27 | 12 | storres | |
28 | 12 | storres | /* Functions */
|
29 | 12 | storres | void
|
30 | 12 | storres | pobyso_autoprint(sollya_obj_t solObj, ...) |
31 | 12 | storres | { |
32 | 12 | storres | va_list va; |
33 | 12 | storres | va_start(va, solObj); |
34 | 12 | storres | sollya_lib_v_autoprint(solObj, va); |
35 | 12 | storres | va_end(va); |
36 | 12 | storres | } /* End pobyso_autoprint. */
|
37 | 12 | storres | |
38 | 12 | storres | sollya_obj_t |
39 | 12 | storres | pobyso_parse_string(const char* expression) |
40 | 12 | storres | { |
41 | 12 | storres | if (expression == NULL) |
42 | 12 | storres | { |
43 | 12 | storres | pobyso_error_message("pobyso_parse_string",
|
44 | 12 | storres | "NULL_POINTER_ARGUMENT",
|
45 | 12 | storres | "The expression is a NULL pointer");
|
46 | 12 | storres | return(NULL); |
47 | 12 | storres | } |
48 | 12 | storres | return(sollya_lib_parse_string(expression));
|
49 | 12 | storres | } /* pobyso_parse_string */
|
50 | 12 | storres | |
51 | 12 | storres | void
|
52 | 12 | storres | pobyso_set_verbosity_off(sollya_obj_t* currentVerbosityLevel) |
53 | 12 | storres | { |
54 | 12 | storres | sollya_obj_t verbosityLevelZero; |
55 | 12 | storres | if (currentVerbosityLevel != NULL) |
56 | 12 | storres | { |
57 | 12 | storres | *currentVerbosityLevel = sollya_lib_get_verbosity(); |
58 | 12 | storres | } |
59 | 12 | storres | verbosityLevelZero = sollya_lib_constant_from_int(0);
|
60 | 12 | storres | sollya_lib_set_verbosity(verbosityLevelZero); |
61 | 12 | storres | sollya_lib_clear_obj(verbosityLevelZero); |
62 | 12 | storres | } /* End of pobyso_set_verbosity_off. */
|
63 | 12 | storres | |
64 | 12 | storres | void
|
65 | 12 | storres | pobyso_set_verbosity_to(sollya_obj_t newVerbosityLevel) |
66 | 12 | storres | { |
67 | 12 | storres | if (newVerbosityLevel == NULL) |
68 | 12 | storres | { |
69 | 12 | storres | pobyso_error_message("pobyso_set_verbosity_to",
|
70 | 12 | storres | "NULL_POINTER_ARGUMENT",
|
71 | 12 | storres | "The new verbosity level is a NULL pointer");
|
72 | 12 | storres | return;
|
73 | 12 | storres | } |
74 | 12 | storres | sollya_lib_set_verbosity(newVerbosityLevel); |
75 | 12 | storres | } /* End of pobyso_set_verbosity_to. */
|
76 | 12 | storres | |
77 | 12 | storres | /* Attic from the sollya_lib < 4. */
|
78 | 12 | storres | #if 0
|
79 | 12 | storres | chain*
|
80 | 12 | storres | pobyso_create_canonical_monomials_base(const unsigned int degree)
|
81 | 12 | storres | {
|
82 | 12 | storres | int i = 0;
|
83 | 12 | storres | chain *monomials = NULL;
|
84 | 12 | storres | node *monomial = NULL;
|
85 | 12 | storres | |
86 | 12 | storres | for(i = degree ; i >= 0 ; i--)
|
87 | 12 | storres | {
|
88 | 12 | storres | monomial = makePow(makeVariable(), makeConstantDouble((double)i));
|
89 | 12 | storres | monomials = addElement(monomials, monomial);
|
90 | 12 | storres | fprintf(stderr, "pobyso_create_canonical_monomials_base: %u\n", i);
|
91 | 12 | storres | }
|
92 | 12 | storres | if (monomials == NULL)
|
93 | 12 | storres | {
|
94 | 12 | storres | pobyso_error_message("pobyso_create_canonical_monomial_base",
|
95 | 12 | storres | "CHAIN_CREATION_ERROR",
|
96 | 12 | storres | "Could not create the monomials chain");
|
97 | 12 | storres | return(NULL);
|
98 | 12 | storres | }
|
99 | 12 | storres | return(monomials);
|
100 | 12 | storres | } /* End pobyso_create_canonical_monomials_base. */
|
101 | 12 | storres | |
102 | 12 | storres | chain*
|
103 | 12 | storres | pobyso_create_chain_from_int_array(int* intArray,
|
104 | 12 | storres | const unsigned int arrayLength)
|
105 | 12 | storres | {
|
106 | 12 | storres | int i = 0;
|
107 | 12 | storres | chain *newChain = NULL;
|
108 | 12 | storres | int *currentInt;
|
109 | 12 | storres | |
110 | 12 | storres | if (arrayLength == 0) return(NULL);
|
111 | 12 | storres | if (intArray == NULL)
|
112 | 12 | storres | {
|
113 | 12 | storres | pobyso_error_message("pobyso_create_chain_from_int_array",
|
114 | 12 | storres | "NULL_POINTER_ARGUMENT",
|
115 | 12 | storres | "The array is a NULL pointer");
|
116 | 12 | storres | return(NULL);
|
117 | 12 | storres | }
|
118 | 12 | storres | for (i = arrayLength - 1 ; i >= 0 ; i--)
|
119 | 12 | storres | {
|
120 | 12 | storres | currentInt = malloc(sizeof(int));
|
121 | 12 | storres | if (currentInt == NULL)
|
122 | 12 | storres | {
|
123 | 12 | storres | pobyso_error_message("pobyso_create_chain_from_int_array",
|
124 | 12 | storres | "MEMORY_ALLOCATION_ERROR",
|
125 | 12 | storres | "Could not allocate one of the integers");
|
126 | 12 | storres | freeChain(newChain, free);
|
127 | 12 | storres | return(NULL);
|
128 | 12 | storres | }
|
129 | 12 | storres | *currentInt = intArray[i];
|
130 | 12 | storres | newChain = addElement(newChain, currentInt);
|
131 | 12 | storres | }
|
132 | 12 | storres | return(newChain);
|
133 | 12 | storres | } // End pobyso_create_chain_from_int_array. */
|
134 | 12 | storres | |
135 | 12 | storres | chain*
|
136 | 12 | storres | pobyso_create_chain_from_unsigned_int_array(unsigned int* intArray,
|
137 | 12 | storres | const unsigned int arrayLength)
|
138 | 12 | storres | {
|
139 | 12 | storres | int i = 0;
|
140 | 12 | storres | chain *newChain = NULL;
|
141 | 12 | storres | unsigned int *currentInt;
|
142 | 12 | storres | |
143 | 12 | storres | /* Argument checking. */
|
144 | 12 | storres | if (arrayLength == 0) return(NULL);
|
145 | 12 | storres | if (intArray == NULL)
|
146 | 12 | storres | {
|
147 | 12 | storres | pobyso_error_message("pobyso_create_chain_from_unsigned_int_array",
|
148 | 12 | storres | "NULL_POINTER_ARGUMENT",
|
149 | 12 | storres | "The array is a NULL pointer");
|
150 | 12 | storres | return(NULL);
|
151 | 12 | storres | }
|
152 | 12 | storres | for (i = arrayLength - 1 ; i >= 0 ; i--)
|
153 | 12 | storres | {
|
154 | 12 | storres | currentInt = malloc(sizeof(unsigned int));
|
155 | 12 | storres | if (currentInt == NULL)
|
156 | 12 | storres | {
|
157 | 12 | storres | pobyso_error_message("pobyso_create_chain_from_unsigned_int_array",
|
158 | 12 | storres | "MEMORY_ALLOCATION_ERROR",
|
159 | 12 | storres | "Could not allocate one of the integers");
|
160 | 12 | storres | freeChain(newChain, free);
|
161 | 12 | storres | return(NULL);
|
162 | 12 | storres | }
|
163 | 12 | storres | *currentInt = intArray[i];
|
164 | 12 | storres | newChain = addElement(newChain, currentInt);
|
165 | 12 | storres | }
|
166 | 12 | storres | return(newChain);
|
167 | 12 | storres | } // End pobyso_create_chain_from_unsigned_int_array. */
|
168 | 12 | storres | |
169 | 12 | storres | node*
|
170 | 12 | storres | pobyso_differentiate(node *functionNode)
|
171 | 12 | storres | {
|
172 | 12 | storres | /* Argument checking. */
|
173 | 12 | storres | node *differentialNode;
|
174 | 12 | storres | if (functionNode == NULL)
|
175 | 12 | storres | {
|
176 | 12 | storres | pobyso_error_message("pobyso_differentiate",
|
177 | 12 | storres | "NULL_POINTER_ARGUMENT",
|
178 | 12 | storres | "The function to differentiate is a NULL pointer");
|
179 | 12 | storres | return(NULL);
|
180 | 12 | storres | }
|
181 | 12 | storres | differentialNode = differentiate(functionNode);
|
182 | 12 | storres | if (differentialNode == NULL)
|
183 | 12 | storres | {
|
184 | 12 | storres | pobyso_error_message("pobyso_differentiate",
|
185 | 12 | storres | "INTERNAL ERROR",
|
186 | 12 | storres | "Sollya could not differentiate the function");
|
187 | 12 | storres | }
|
188 | 12 | storres | return(differentialNode);
|
189 | 12 | storres | } // End pobyso_differentiate
|
190 | 12 | storres | |
191 | 12 | storres | |
192 | 12 | storres | int
|
193 | 12 | storres | pobyso_dirty_infnorm(mpfr_t infNorm,
|
194 | 12 | storres | node *functionNode,
|
195 | 12 | storres | mpfr_t lowerBound,
|
196 | 12 | storres | mpfr_t upperBound,
|
197 | 12 | storres | mp_prec_t precision)
|
198 | 12 | storres | {
|
199 | 12 | storres | int functionCallResult;
|
200 | 12 | storres | /* Arguments checking. */
|
201 | 12 | storres | if (functionNode == NULL)
|
202 | 12 | storres | {
|
203 | 12 | storres | pobyso_error_message("pobyso_dirty_infnorm",
|
204 | 12 | storres | "NULL_POINTER_ARGUMENT",
|
205 | 12 | storres | "The function to compute is a NULL pointer");
|
206 | 12 | storres | return(1);
|
207 | 12 | storres | }
|
208 | 12 | storres | if (mpfr_cmp(lowerBound, upperBound) > 0)
|
209 | 12 | storres | {
|
210 | 12 | storres | pobyso_error_message("pobyso_dirty_infnorm",
|
211 | 12 | storres | "INCOHERENT_INPUT_DATA",
|
212 | 12 | storres | "The lower bond is greater than the upper bound");
|
213 | 12 | storres | return(1);
|
214 | 12 | storres | }
|
215 | 12 | storres | /* Particular cases. */
|
216 | 12 | storres | if (mpfr_cmp(lowerBound, upperBound) == 0)
|
217 | 12 | storres | {
|
218 | 12 | storres | functionCallResult = pobyso_evaluate_faithful(infNorm,
|
219 | 12 | storres | functionNode,
|
220 | 12 | storres | lowerBound,
|
221 | 12 | storres | precision);
|
222 | 12 | storres | return(functionCallResult);
|
223 | 12 | storres | }
|
224 | 12 | storres | if (isConstant(functionNode))
|
225 | 12 | storres | {
|
226 | 12 | storres | functionCallResult = pobyso_evaluate_faithful(infNorm,
|
227 | 12 | storres | functionNode,
|
228 | 12 | storres | lowerBound,
|
229 | 12 | storres | precision);
|
230 | 12 | storres | if (!functionCallResult)
|
231 | 12 | storres | {
|
232 | 12 | storres | mpfr_abs(infNorm, infNorm, MPFR_RNDN);
|
233 | 12 | storres | }
|
234 | 12 | storres | return(functionCallResult);
|
235 | 12 | storres | }
|
236 | 12 | storres | uncertifiedInfnorm(infNorm,
|
237 | 12 | storres | functionNode,
|
238 | 12 | storres | lowerBound,
|
239 | 12 | storres | upperBound,
|
240 | 12 | storres | POBYSO_DEFAULT_POINTS,
|
241 | 12 | storres | precision);
|
242 | 12 | storres | return(0);
|
243 | 12 | storres | } /* End pobyso_dirty_infnorm. */
|
244 | 12 | storres | |
245 | 12 | storres | int
|
246 | 12 | storres | pobyso_evaluate_faithful(mpfr_t faithfulEvaluation,
|
247 | 12 | storres | node *nodeToEvaluate,
|
248 | 12 | storres | mpfr_t argument,
|
249 | 12 | storres | mpfr_prec_t precision)
|
250 | 12 | storres | {
|
251 | 12 | storres | /* Check input arguments. */
|
252 | 12 | storres | if (nodeToEvaluate == NULL)
|
253 | 12 | storres | {
|
254 | 12 | storres | pobyso_error_message("pobyso_evaluate_faithful",
|
255 | 12 | storres | "NULL_POINTER_ARGUMENT",
|
256 | 12 | storres | "nodeToEvaluate is a NULL pointer");
|
257 | 12 | storres | return(1);
|
258 | 12 | storres | }
|
259 | 12 | storres | evaluateFaithful(faithfulEvaluation,
|
260 | 12 | storres | nodeToEvaluate,
|
261 | 12 | storres | argument,
|
262 | 12 | storres | precision);
|
263 | 12 | storres | return(0);
|
264 | 12 | storres | } /* End pobyso_evaluate_faithfull. */
|
265 | 12 | storres | |
266 | 12 | storres | chain*
|
267 | 12 | storres | pobyso_find_zeros(node *function,
|
268 | 12 | storres | mpfr_t *lower_bound,
|
269 | 12 | storres | mpfr_t *upper_bound)
|
270 | 12 | storres | {
|
271 | 12 | storres | mp_prec_t currentPrecision;
|
272 | 12 | storres | mpfr_t currentDiameter;
|
273 | 12 | storres | rangetype bounds;
|
274 | 12 | storres | |
275 | 12 | storres | currentPrecision = getToolPrecision();
|
276 | 12 | storres | mpfr_init2(currentDiameter, currentPrecision);
|
277 | 12 | storres | |
278 | 12 | storres | bounds.a = lower_bound;
|
279 | 12 | storres | bounds.b = upper_bound;
|
280 | 12 | storres | |
281 | 12 | storres | if (bounds.a == NULL || bounds.b == NULL)
|
282 | 12 | storres | {
|
283 | 12 | storres | pobyso_error_message("pobyso_find_zeros",
|
284 | 12 | storres | "MEMORY_ALLOCATION_ERROR",
|
285 | 12 | storres | "Could not allocate one of the bounds");
|
286 | 12 | storres | return(NULL);
|
287 | 12 | storres | }
|
288 | 12 | storres | return(findZerosFunction(function,
|
289 | 12 | storres | bounds,
|
290 | 12 | storres | currentPrecision,
|
291 | 12 | storres | currentDiameter));
|
292 | 12 | storres | } /* End pobyso_find_zeros. */
|
293 | 12 | storres | |
294 | 12 | storres | void
|
295 | 12 | storres | pobyso_free_chain_of_nodes(chain *theChainOfNodes)
|
296 | 12 | storres | {
|
297 | 12 | storres | node *currentNode = NULL;
|
298 | 12 | storres | chain *currentChainElement = NULL;
|
299 | 12 | storres | chain *nextChainElement = NULL;
|
300 | 12 | storres | |
301 | 12 | storres | nextChainElement = theChainOfNodes;
|
302 | 12 | storres | |
303 | 12 | storres | while(nextChainElement != NULL)
|
304 | 12 | storres | {
|
305 | 12 | storres | currentChainElement = nextChainElement;
|
306 | 12 | storres | currentNode = (node*)(currentChainElement->value);
|
307 | 12 | storres | nextChainElement = nextChainElement->next;
|
308 | 12 | storres | free_memory(currentNode);
|
309 | 12 | storres | free((void*)(currentChainElement));
|
310 | 12 | storres | }
|
311 | 12 | storres | } /* End pobyso_free_chain_of_nodes. */
|
312 | 12 | storres | |
313 | 12 | storres | void
|
314 | 12 | storres | pobyso_free_range(rangetype range)
|
315 | 12 | storres | {
|
316 | 12 | storres | |
317 | 12 | storres | mpfr_clear(*(range.a));
|
318 | 12 | storres | mpfr_clear(*(range.b));
|
319 | 12 | storres | free(range.a);
|
320 | 12 | storres | free(range.b);
|
321 | 12 | storres | } /* End pobyso_free_range. */
|
322 | 12 | storres | |
323 | 12 | storres | node*
|
324 | 12 | storres | pobyso_fp_minimax_canonical_monomials_base(node *function,
|
325 | 12 | storres | int degree,
|
326 | 12 | storres | chain *formats,
|
327 | 12 | storres | chain *points,
|
328 | 12 | storres | mpfr_t lowerBound,
|
329 | 12 | storres | mpfr_t upperBound,
|
330 | 12 | storres | int fpFixedArg,
|
331 | 12 | storres | int absRel,
|
332 | 12 | storres | node *constPart,
|
333 | 12 | storres | node *minimax)
|
334 | 12 | storres | {
|
335 | 12 | storres | return(NULL);
|
336 | 12 | storres | } /* End pobyso_fp_minimax_canonical_monomials_base. */
|
337 | 12 | storres | |
338 | 12 | storres | node*
|
339 | 12 | storres | pobyso_parse_function(char *functionString,
|
340 | 12 | storres | char *freeVariableNameString)
|
341 | 12 | storres | {
|
342 | 12 | storres | if (functionString == NULL || freeVariableNameString == NULL)
|
343 | 12 | storres | {
|
344 | 12 | storres | pobyso_error_message("pobyso_parse_function",
|
345 | 12 | storres | "NULL_POINTER_ARGUMENT",
|
346 | 12 | storres | "One of the arguments is a NULL pointer");
|
347 | 12 | storres | return(NULL);
|
348 | 12 | storres | }
|
349 | 12 | storres | return(parseString(functionString));
|
350 | 12 | storres | |
351 | 12 | storres | } /* End pobyso_parse_function */
|
352 | 12 | storres | |
353 | 12 | storres | node*
|
354 | 12 | storres | pobyso_remez_approx_canonical_monomials_base_for_error(node *functionNode,
|
355 | 12 | storres | unsigned int mode,
|
356 | 12 | storres | mpfr_t lowerBound,
|
357 | 12 | storres | mpfr_t upperBound,
|
358 | 12 | storres | mpfr_t eps)
|
359 | 12 | storres | {
|
360 | 12 | storres | node *weight = NULL;
|
361 | 12 | storres | node *bestApproxPolyNode = NULL;
|
362 | 12 | storres | node *bestApproxHorner = NULL;
|
363 | 12 | storres | node *errorNode = NULL;
|
364 | 12 | storres | rangetype degreeRange;
|
365 | 12 | storres | mpfr_t quality;
|
366 | 12 | storres | mpfr_t currentError;
|
367 | 12 | storres | unsigned int degree;
|
368 | 12 | storres | |
369 | 12 | storres | /* Check the parameters. */
|
370 | 12 | storres | if (functionNode == NULL)
|
371 | 12 | storres | {
|
372 | 12 | storres | pobyso_error_message("remezApproxCanonicalMonomialsBaseForError",
|
373 | 12 | storres | "NULL_POINTER_ARGUMENT",
|
374 | 12 | storres | "functionNode is a NULL pointer");
|
375 | 12 | storres | return(NULL);
|
376 | 12 | storres | }
|
377 | 12 | storres | if (mpfr_cmp(lowerBound, upperBound) >= 0)
|
378 | 12 | storres | {
|
379 | 12 | storres | pobyso_error_message("remezApproxCanonicalMonomialsBaseForError",
|
380 | 12 | storres | "INCOHERENT_INPUT_DATA",
|
381 | 12 | storres | "the lower_bound >= upper_bound");
|
382 | 12 | storres | return(NULL);
|
383 | 12 | storres | }
|
384 | 12 | storres | /* Set the weight. */
|
385 | 12 | storres | if (mode == POBYSO_ABSOLUTE)
|
386 | 12 | storres | {
|
387 | 12 | storres | /* Set the weight to 1 for the ABSOLUTE_MODE. */
|
388 | 12 | storres | weight = makeConstantDouble(1.0);
|
389 | 12 | storres | }
|
390 | 12 | storres | else
|
391 | 12 | storres | {
|
392 | 12 | storres | if (mode == POBYSO_RELATIVE)
|
393 | 12 | storres | {
|
394 | 12 | storres | pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
|
395 | 12 | storres | "NOT_IMPLEMENTED",
|
396 | 12 | storres | "the search for relative error is not implemented yet");
|
397 | 12 | storres | return(NULL);
|
398 | 12 | storres | }
|
399 | 12 | storres | else
|
400 | 12 | storres | {
|
401 | 12 | storres | pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
|
402 | 12 | storres | "INCOHERENT_INPUT_DATA",
|
403 | 12 | storres | "the mode is node of POBYSO_ABOLUTE or POBYSO_RELATIVE");
|
404 | 12 | storres | return(NULL);
|
405 | 12 | storres | }
|
406 | 12 | storres | }
|
407 | 12 | storres | //fprintf(stderr, "\n\n\n******* I'm here! ********\n\n\n");
|
408 | 12 | storres | degreeRange = guessDegree(functionNode,
|
409 | 12 | storres | weight,
|
410 | 12 | storres | lowerBound,
|
411 | 12 | storres | upperBound,
|
412 | 12 | storres | eps,
|
413 | 12 | storres | POBYSO_GUESS_DEGREE_BOUND);
|
414 | 12 | storres | degree = mpfr_get_ui(*(degreeRange.a), MPFR_RNDN);
|
415 | 12 | storres | //fprintf(stderr, "\n\n\n******* I'm back! ********\n\n\n");
|
416 | 12 | storres | fprintf(stderr, "Guessed degree: ");
|
417 | 12 | storres | mpfr_out_str(stderr, 10, 17, *(degreeRange.a), MPFR_RNDN);
|
418 | 12 | storres | fprintf(stderr, " - as int: %u\n", degree);
|
419 | 12 | storres | /* Reduce the degree by 1 in the foolish hope it could work. */
|
420 | 12 | storres | if (degree > 0) degree--;
|
421 | 12 | storres | /* Both elements of degreeRange where "inited" within guessDegree. */
|
422 | 12 | storres | mpfr_clear(*(degreeRange.a));
|
423 | 12 | storres | mpfr_clear(*(degreeRange.b));
|
424 | 12 | storres | free(degreeRange.a);
|
425 | 12 | storres | free(degreeRange.b);
|
426 | 12 | storres | /* Mimic the default behavior of interactive Sollya. */
|
427 | 12 | storres | mpfr_init(quality);
|
428 | 12 | storres | mpfr_set_d(quality, 1e-5, MPFR_RNDN);
|
429 | 12 | storres | mpfr_init2(currentError, getToolPrecision());
|
430 | 12 | storres | mpfr_set_inf(currentError,1);
|
431 | 12 | storres | |
432 | 12 | storres | /* Try to refine the initial guess: loop with increasing degrees until
|
433 | 12 | storres | * we find a satisfactory one. */
|
434 | 12 | storres | while(mpfr_cmp(currentError, eps) > 0)
|
435 | 12 | storres | {
|
436 | 12 | storres | /* Get rid of the previous polynomial, if any. */
|
437 | 12 | storres | if (bestApproxPolyNode != NULL)
|
438 | 12 | storres | {
|
439 | 12 | storres | free_memory(bestApproxPolyNode);
|
440 | 12 | storres | }
|
441 | 12 | storres | fprintf(stderr, "Degree: %u\n", degree);
|
442 | 12 | storres | fprintf(stderr, "Calling pobyso_remez_canonical_monomials_base...\n");
|
443 | 12 | storres | /* Try to find a polynomial with the guessed degree. */
|
444 | 12 | storres | bestApproxPolyNode = pobyso_remez_canonical_monomials_base(functionNode,
|
445 | 12 | storres | weight,
|
446 | 12 | storres | degree,
|
447 | 12 | storres | lowerBound,
|
448 | 12 | storres | upperBound,
|
449 | 12 | storres | quality);
|
450 | 12 | storres | |
451 | 12 | storres | if (bestApproxPolyNode == NULL)
|
452 | 12 | storres | {
|
453 | 12 | storres | pobyso_error_message("computeRemezApproxCanonicalMonomialsBaseForError",
|
454 | 12 | storres | "INTERNAL_ERROR",
|
455 | 12 | storres | "could not compute the bestApproxPolyNode");
|
456 | 12 | storres | mpfr_clear(currentError);
|
457 | 12 | storres | mpfr_clear(quality);
|
458 | 12 | storres | return(NULL);
|
459 | 12 | storres | }
|
460 | 12 | storres | |
461 | 12 | storres | setDisplayMode(DISPLAY_MODE_DECIMAL);
|
462 | 12 | storres | fprintTree(stderr, bestApproxPolyNode);
|
463 | 12 | storres | fprintf(stderr, "\n\n");
|
464 | 12 | storres | |
465 | 12 | storres | errorNode = makeSub(copyTree(functionNode), copyTree(bestApproxPolyNode));
|
466 | 12 | storres | /* Check the error with the computed polynomial. */
|
467 | 12 | storres | uncertifiedInfnorm(currentError,
|
468 | 12 | storres | errorNode,
|
469 | 12 | storres | lowerBound,
|
470 | 12 | storres | upperBound,
|
471 | 12 | storres | POBYSO_INF_NORM_NUM_POINTS,
|
472 | 12 | storres | getToolPrecision());
|
473 | 12 | storres | fprintf(stderr, "Inf norm: ");
|
474 | 12 | storres | mpfr_out_str(stderr, 10, 17, currentError, MPFR_RNDN);
|
475 | 12 | storres | fprintf(stderr, "\n\n");
|
476 | 12 | storres | /* Free the errorNode but not the bestApproxPolyNode (we need it if
|
477 | 12 | storres | * we exit the loop at the next iteration). */
|
478 | 12 | storres | free_memory(errorNode);
|
479 | 12 | storres | degree++;
|
480 | 12 | storres | }
|
481 | 12 | storres | /* Use an intermediate variable, since horner() creates a new node
|
482 | 12 | storres | * and does not reorder the argument "in place". This allows for the memory
|
483 | 12 | storres | * reclaim of bestApproxHorner.
|
484 | 12 | storres | */
|
485 | 12 | storres | bestApproxHorner = horner(bestApproxPolyNode);
|
486 | 12 | storres | free_memory(bestApproxPolyNode);
|
487 | 12 | storres | mpfr_clear(currentError);
|
488 | 12 | storres | mpfr_clear(quality);
|
489 | 12 | storres | free_memory(weight);
|
490 | 12 | storres | return(bestApproxHorner);
|
491 | 12 | storres | } /* End pobyso_remez_approx_canonical_monomials_base_for_error */
|
492 | 12 | storres | |
493 | 12 | storres | node*
|
494 | 12 | storres | pobyso_remez_canonical_monomials_base(node *function,
|
495 | 12 | storres | node *weight,
|
496 | 12 | storres | unsigned int degree,
|
497 | 12 | storres | mpfr_t lowerBound,
|
498 | 12 | storres | mpfr_t upperBound,
|
499 | 12 | storres | mpfr_t quality)
|
500 | 12 | storres | {
|
501 | 12 | storres | node *bestApproxPoly = NULL;
|
502 | 12 | storres | chain *monomials = NULL;
|
503 | 12 | storres | chain *curMonomial = NULL;
|
504 | 12 | storres | |
505 | 12 | storres | mpfr_t satisfying_error;
|
506 | 12 | storres | mpfr_t target_error;
|
507 | 12 | storres | |
508 | 12 | storres | /* Argument checking */
|
509 | 12 | storres | /* Function tree. */
|
510 | 12 | storres | if (function == NULL)
|
511 | 12 | storres | {
|
512 | 12 | storres | pobyso_error_message("pobyso_remez_canonical_monomials_base",
|
513 | 12 | storres | "NULL_POINTER_ARGUMENT",
|
514 | 12 | storres | "the \"function\" argument is a NULL pointer");
|
515 | 12 | storres | return(NULL);
|
516 | 12 | storres | }
|
517 | 12 | storres | if (weight == NULL)
|
518 | 12 | storres | {
|
519 | 12 | storres | pobyso_error_message("pobyso_remez_canonical_monomials_base",
|
520 | 12 | storres | "NULL_POINTER_ARGUMENT",
|
521 | 12 | storres | "the \"weight\" argument is a NULL pointer");
|
522 | 12 | storres | return(NULL);
|
523 | 12 | storres | }
|
524 | 12 | storres | /* Check the bounds. */
|
525 | 12 | storres | if (mpfr_cmp(lowerBound, upperBound) >= 0)
|
526 | 12 | storres | {
|
527 | 12 | storres | pobyso_error_message("pobyso_remez_canonical_monomials_base",
|
528 | 12 | storres | "INCOHERENT_IMPUT_DATA",
|
529 | 12 | storres | "the lower_bound >= upper_bound");
|
530 | 12 | storres | return(NULL);
|
531 | 12 | storres | }
|
532 | 12 | storres | /* The quality must be a non null positive number. */
|
533 | 12 | storres | if (mpfr_sgn(quality) <= 0)
|
534 | 12 | storres | {
|
535 | 12 | storres | pobyso_error_message("pobyso_remez_canonical_monomials_base",
|
536 | 12 | storres | "INCOHERENT_INPUT_DATA",
|
537 | 12 | storres | "the quality <= 0");
|
538 | 12 | storres | }
|
539 | 12 | storres | /* End argument checking. */
|
540 | 12 | storres | /* Create the monomials nodes chains. */
|
541 | 12 | storres | monomials = pobyso_create_canonical_monomials_base(degree);
|
542 | 12 | storres | fprintf(stderr, "monomials chain length = %d\n", lengthChain(monomials));
|
543 | 12 | storres | if (monomials == NULL || (lengthChain(monomials) != degree + 1))
|
544 | 12 | storres | {
|
545 | 12 | storres | pobyso_error_message("pobyso_remez_canonical_monomials_base",
|
546 | 12 | storres | "CHAIN_CREATION_ERROR",
|
547 | 12 | storres | "could not create the monomials chain");
|
548 | 12 | storres | return(NULL);
|
549 | 12 | storres | }
|
550 | 12 | storres | curMonomial = monomials;
|
551 | 12 | storres | |
552 | 12 | storres | while (curMonomial != NULL)
|
553 | 12 | storres | {
|
554 | 12 | storres | fprintf(stderr, "monomial tree: ");
|
555 | 12 | storres | //mpfr_out_str(stderr, 10, 17, *((mpfr_t*)((node*)(curMonomial->value))->value), MPFR_RNDN);
|
556 | 12 | storres | fprintTree(stderr, (node*)(curMonomial->value));
|
557 | 12 | storres | fprintf(stderr, "\n");
|
558 | 12 | storres | curMonomial = curMonomial->next;
|
559 | 12 | storres | }
|
560 | 12 | storres | |
561 | 12 | storres | /* Deal with NULL weight. */
|
562 | 12 | storres | if (weight == NULL)
|
563 | 12 | storres | {
|
564 | 12 | storres | weight = makeConstantDouble(1.0);
|
565 | 12 | storres | }
|
566 | 12 | storres | /* Compute the best polynomial with the required quality.
|
567 | 12 | storres | The behavior is as if satisfying error and target_error had
|
568 | 12 | storres | not been used.*/
|
569 | 12 | storres | mpfr_init(satisfying_error);
|
570 | 12 | storres | mpfr_init(target_error);
|
571 | 12 | storres | mpfr_set_str(satisfying_error, "0", 10, MPFR_RNDN);
|
572 | 12 | storres | mpfr_set_inf(target_error, 1);
|
573 | 12 | storres | |
574 | 12 | storres | |
575 | 12 | storres | fprintf(stderr, "satisfying_error: ");
|
576 | 12 | storres | mpfr_out_str(stderr, 10, 17, satisfying_error, MPFR_RNDN);
|
577 | 12 | storres | fprintf(stderr, ".\n");
|
578 | 12 | storres | fprintf(stderr, "target_error: ");
|
579 | 12 | storres | mpfr_out_str(stderr, 10, 17, target_error,MPFR_RNDN);
|
580 | 12 | storres | fprintf(stderr, ".\n");
|
581 | 12 | storres | |
582 | 12 | storres | fprintf(stderr,
|
583 | 12 | storres | "current precision: %li\n", getToolPrecision());
|
584 | 12 | storres | /* Call the Sollya function. */
|
585 | 12 | storres | bestApproxPoly = remez(function,
|
586 | 12 | storres | weight,
|
587 | 12 | storres | monomials,
|
588 | 12 | storres | lowerBound,
|
589 | 12 | storres | upperBound,
|
590 | 12 | storres | quality,
|
591 | 12 | storres | satisfying_error,
|
592 | 12 | storres | target_error,
|
593 | 12 | storres | getToolPrecision());
|
594 | 12 | storres | |
595 | 12 | storres | mpfr_clear(satisfying_error);
|
596 | 12 | storres | mpfr_clear(target_error);
|
597 | 12 | storres | pobyso_free_chain_of_nodes(monomials);
|
598 | 12 | storres | |
599 | 12 | storres | return(bestApproxPoly);
|
600 | 12 | storres | } /* End pobyso_remez_canonical_monomials_base. */
|
601 | 12 | storres | |
602 | 12 | storres | #endif
|
603 | 12 | storres | |
604 | 12 | storres | void
|
605 | 12 | storres | pobyso_error_message(char *functionName, char *messageName, char* message) |
606 | 12 | storres | { |
607 | 12 | storres | fprintf(stderr, "?%s: %s.\n%s.\n", functionName, messageName, message);
|
608 | 12 | storres | } /* End pobyso_error_message */ |