1 /*
2 * This file is part of MPSolve 3.2.1
3 *
4 * Copyright (C) 2001-2020, Dipartimento di Matematica "L. Tonelli", Pisa.
5 * License: http://www.gnu.org/licenses/gpl.html GPL version 3 or higher
6 *
7 * Authors:
8 * Dario Andrea Bini <bini@dm.unipi.it>
9 * Giuseppe Fiorentino <fiorent@dm.unipi.it>
10 * Leonardo Robol <leonardo.robol@unipi.it>
11 */
12
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <math.h>
17 #include <float.h>
18 #include <limits.h>
19 #include <mps/mt.h>
20 #include <mps/mps.h>
21
22 /***********************************************************
23 ** machine dependent constants **
24 ***********************************************************/
25
26 #define NBT DBL_MANT_DIG
27
28 /***********************************************************
29 ** input/output formats **
30 ***********************************************************/
31
32 #define FMTE "% 18.14e"
33 #define FMTF "% 16.14f"
34 #define CPLX_OUT_UFMT FMTE " " FMTE
35 #define CPLX_OUT_FMT "(" FMTE ", " FMTE ")"
36 #define CPLX_INP_UFMT "%le %le"
37 #define CPLX_INP_FMT "(%le, %le)"
38 #define RDPE_OUT_UFMT FMTF "e%+04li"
39 #define RDPE_OUT_FMT FMTF "x%+04li"
40 #define RDPE_INP_UFMT "%lf e %ld"
41 #define RDPE_INP_FMT "%lf x %ld"
42 #define CDPE_OUT_UFMT RDPE_OUT_UFMT " " RDPE_OUT_UFMT
43 #define CDPE_OUT_FMT "(" RDPE_OUT_FMT ", " RDPE_OUT_FMT ")"
44 #define CDPE_INP_UFMT RDPE_INP_UFMT " " RDPE_INP_UFMT
45 #define CDPE_INP_FMT "(" RDPE_INP_FMT ", " RDPE_INP_FMT ")"
46 #define DEF_STR_SIZE 80
47
48 /***********************************************************
49 ** numerical constants **
50 ***********************************************************/
51
52 #define LOG10_2 0.30102999566398119521
53 #define LOG2_10 3.32192809488736234787
54 #define LOG_2 0.69314718055994530941
55 #define LOG_10 2.30258509299404568401
56
57 /***********************************************************
58 ** functions for cplx_t **
59 ***********************************************************/
60
61 #ifdef MPS_USE_BUILTIN_COMPLEX
62
63 /* base constants */
64 const cplx_t cplx_zero = { { 0.0, 0.0 } };
65 const cplx_t cplx_one = { { 1.0, 0.0 } };
66 const cplx_t cplx_i = { { 0.0, 1.0 } };
67
68 void
cplx_d(cplx_t temp_cplx,double r,double i)69 cplx_d (cplx_t temp_cplx, double r, double i)
70 /* return (r, i) */
71 {
72 cplx_Re (temp_cplx) = r;
73 cplx_Im (temp_cplx) = i;
74 }
75
76 void
cplx_clear(cplx_t x)77 cplx_clear (cplx_t x)
78 /* x = 0 + I 0 */
79 {
80 cplx_Move (x, cplx_zero);
81 }
82
83 void
cplx_set(cplx_t rx,const cplx_t x)84 cplx_set (cplx_t rx, const cplx_t x)
85 /* rx = x */
86 {
87 cplx_Move (rx, x);
88 }
89
90 void
cplx_set_d(cplx_t x,double dr,double di)91 cplx_set_d (cplx_t x, double dr, double di)
92 /* x = dr + I di */
93 {
94 cplx_Re (x) = dr;
95 cplx_Im (x) = di;
96 }
97
98 int
cplx_set_str(cplx_t x,const char * s)99 cplx_set_str (cplx_t x, const char *s)
100 /* set from string as (re , im) */
101 {
102 return sscanf (s, CPLX_INP_FMT, &cplx_Re (x), &cplx_Im (x)) == 2;
103 }
104
105 void
cplx_get_d(double * dr,double * di,const cplx_t x)106 cplx_get_d (double *dr, double *di, const cplx_t x)
107 /* *dr = re(x), *di = im(x) */
108 {
109 *dr = cplx_Re (x);
110 *di = cplx_Im (x);
111 }
112
113 char *
cplx_get_str(char * s,const cplx_t x)114 cplx_get_str (char *s, const cplx_t x)
115 /* output to string as (re , im) */
116 {
117 if (s == NULL && (s = (char*)mps_malloc (DEF_STR_SIZE)) == NULL)
118 return NULL;
119 sprintf (s, CPLX_OUT_FMT, cplx_Re (x), cplx_Im (x));
120 return s;
121 }
122
123 void
cplx_neg(cplx_t rx,const cplx_t x)124 cplx_neg (cplx_t rx, const cplx_t x)
125 /* rx = -x */
126 {
127 cplx_Re (rx) = -cplx_Re (x);
128 cplx_Im (rx) = -cplx_Im (x);
129 }
130
131 void
cplx_con(cplx_t rx,const cplx_t x)132 cplx_con (cplx_t rx, const cplx_t x)
133 /* rx = conj(x) */
134 {
135 cplx_Re (rx) = cplx_Re (x);
136 cplx_Im (rx) = -cplx_Im (x);
137 }
138
139 double
cplx_smod(const cplx_t x)140 cplx_smod (const cplx_t x)
141 /* returns |x|^2 */
142 {
143 return cplx_Re (x) * cplx_Re (x) + cplx_Im (x) * cplx_Im (x);
144 }
145
146 double
cplx_mod(const cplx_t x)147 cplx_mod (const cplx_t x)
148 /* returns |x| */
149 {
150 double d;
151
152 if (fabs (cplx_Re (x)) > fabs (cplx_Im (x)))
153 {
154 d = cplx_Im (x) / cplx_Re (x);
155 return fabs (cplx_Re (x)) * sqrt (1.0 + d * d);
156 }
157 else if (cplx_Im (x) == 0.0)
158 return 0.0;
159 d = cplx_Re (x) / cplx_Im (x);
160 return fabs (cplx_Im (x)) * sqrt (1.0 + d * d);
161 }
162
163 void
cplx_inv(cplx_t rx,const cplx_t x)164 cplx_inv (cplx_t rx, const cplx_t x)
165 /* rx = 1 / x */
166 {
167 double d1, d2;
168
169 if (fabs (cplx_Re (x)) > fabs (cplx_Im (x)))
170 {
171 d1 = cplx_Im (x) / cplx_Re (x);
172 d2 = 1.0 / (cplx_Re (x) * (1.0 + d1 * d1));
173 cplx_Re (rx) = d2;
174 cplx_Im (rx) = -d2 * d1;
175 }
176 else
177 {
178 d1 = cplx_Re (x) / cplx_Im (x);
179 d2 = 1.0 / (cplx_Im (x) * (1.0 + d1 * d1));
180 cplx_Im (rx) = -d2;
181 cplx_Re (rx) = d2 * d1;
182 }
183 }
184
185 void
cplx_sqr(cplx_t rx,const cplx_t x)186 cplx_sqr (cplx_t rx, const cplx_t x)
187 /* rx = x * x */
188 {
189 double d; /* necessary when rx=x1 or rx=x2 */
190
191 d = cplx_Re (x) * cplx_Re (x) - cplx_Im (x) * cplx_Im (x);
192 cplx_Im (rx) = 2.0 * cplx_Re (x) * cplx_Im (x);
193 cplx_Re (rx) = d;
194 }
195
196 void
cplx_rot(cplx_t rx,const cplx_t x)197 cplx_rot (cplx_t rx, const cplx_t x)
198 /* rx = I x */
199 {
200 double t;
201
202 t = cplx_Re (x);
203 cplx_Re (rx) = -cplx_Im (x);
204 cplx_Im (rx) = t;
205 }
206
207 void
cplx_flip(cplx_t rx,const cplx_t x)208 cplx_flip (cplx_t rx, const cplx_t x)
209 /* rx = (Im(x), Re(x)) */
210 {
211 double t;
212
213 t = cplx_Re (x);
214 cplx_Re (rx) = cplx_Im (x);
215 cplx_Im (rx) = t;
216 }
217
218 /**
219 * @brief Add the complex number <code>x1</code> and <code>x2</code> and
220 * store the result in <code>rx</code>
221 *
222 * @param rx The place where the result will be stored.
223 * @param x1 The left operand of the addition.
224 * @param x2 The right operand of the addition.
225 */
226 void
cplx_add(cplx_t rx,const cplx_t x1,const cplx_t x2)227 cplx_add (cplx_t rx, const cplx_t x1, const cplx_t x2)
228 /* rx = x1 + x2 */
229 {
230 cplx_Re (rx) = cplx_Re (x1) + cplx_Re (x2);
231 cplx_Im (rx) = cplx_Im (x1) + cplx_Im (x2);
232 }
233
234 /**
235 * @brief Substract from <code>x1</code> the value
236 * stored in <code>x2</code> and store the result
237 * in <code>rx</code>.
238 *
239 * @param rx The place where the result will be stored.
240 * @param x1 The left operand of the subtraction.
241 * @param x2 The right operand of the subtraction.
242 */
243 void
cplx_sub(cplx_t rx,const cplx_t x1,const cplx_t x2)244 cplx_sub (cplx_t rx, const cplx_t x1, const cplx_t x2)
245 /* rx = x1 - x2 */
246 {
247 cplx_Re (rx) = cplx_Re (x1) - cplx_Re (x2);
248 cplx_Im (rx) = cplx_Im (x1) - cplx_Im (x2);
249 }
250
251 /**
252 * @brief Multiply the value stored in <code>x1</code>
253 * and in <code>x2</code> and store the result in
254 * <code>rx</code>.
255 *
256 * @param rx The place where the result wil be stored.
257 * @param x1 The left operand of the multiplication.
258 * @param x2 The right operando of the multiplication.
259 */
260 void
cplx_mul(cplx_t rx,const cplx_t x1,const cplx_t x2)261 cplx_mul (cplx_t rx, const cplx_t x1, const cplx_t x2)
262 /* rx = x1 * x2 */
263 {
264 double d; /* necessary when rx=x1 or rx=x2 */
265
266 d = cplx_Re (x1) * cplx_Re (x2) - cplx_Im (x1) * cplx_Im (x2);
267 cplx_Im (rx) = cplx_Im (x1) * cplx_Re (x2) + cplx_Re (x1) * cplx_Im (x2);
268 cplx_Re (rx) = d;
269 }
270
271 void
cplx_mul_d(cplx_t rx,const cplx_t x,double d)272 cplx_mul_d (cplx_t rx, const cplx_t x, double d)
273 /* rx = x * d */
274 {
275 cplx_Re (rx) = cplx_Re (x) * d;
276 cplx_Im (rx) = cplx_Im (x) * d;
277 }
278
279 /**
280 * @brief Divide the complex value in <code>x1</code> by the
281 * value in <code>x2</code> and store the results in <code>rx</code>.
282 *
283 * @param rx The place where the result will be stored.
284 * @param x1 The left operand of the division.
285 * @param x2 The right operando of the division.
286 */
287 void
cplx_div(cplx_t rx,const cplx_t x1,const cplx_t x2)288 cplx_div (cplx_t rx, const cplx_t x1, const cplx_t x2)
289 /* rx = x1 / x2 */
290 {
291 cplx_t ctmp;
292
293 cplx_inv (ctmp, x2);
294 cplx_mul (rx, x1, ctmp);
295 }
296
297 void
cplx_div_d(cplx_t rx,const cplx_t x,double d)298 cplx_div_d (cplx_t rx, const cplx_t x, double d)
299 /* rx = x / d */
300 {
301 cplx_Re (rx) = cplx_Re (x) / d;
302 cplx_Im (rx) = cplx_Im (x) / d;
303 }
304
305 void
cplx_pow_si(cplx_t rx,const cplx_t x,register signed long int i)306 cplx_pow_si (cplx_t rx, const cplx_t x, register signed long int i)
307 /* rx = x ^ i , i integer */
308 {
309 cplx_t t;
310
311 cplx_Move (t, x);
312 cplx_Move (rx, cplx_one);
313
314 if (i < 0)
315 {
316 cplx_inv_eq (t);
317 i = -i;
318 }
319 while (i)
320 {
321 if (i & 1)
322 cplx_mul_eq (rx, t);
323 cplx_sqr_eq (t);
324 i >>= 1; /* divide i by 2 */
325 }
326 }
327
328 void
cplx_swap(cplx_t x1,cplx_t x2)329 cplx_swap (cplx_t x1, cplx_t x2)
330 /* x1 <-> x2 */
331 {
332 cplx_t t;
333
334 cplx_Move (t, x1);
335 cplx_Move (x1, x2);
336 cplx_Move (x2, t);
337 }
338
339 void
cplx_neg_eq(cplx_t x)340 cplx_neg_eq (cplx_t x)
341 /* x = -x */
342 {
343 cplx_Re (x) = -cplx_Re (x);
344 cplx_Im (x) = -cplx_Im (x);
345 }
346
347 void
cplx_con_eq(cplx_t x)348 cplx_con_eq (cplx_t x)
349 /* x = conj(x) */
350 {
351 cplx_Im (x) = -cplx_Im (x);
352 }
353
354 void
cplx_inv_eq(cplx_t x)355 cplx_inv_eq (cplx_t x)
356 /* rx = 1 / x */
357 {
358 double d1, d2;
359
360 if (fabs (cplx_Re (x)) > fabs (cplx_Im (x)))
361 {
362 d1 = cplx_Im (x) / cplx_Re (x);
363 if (DBL_MAX / (1.0 + d1 * d1) < fabs (cplx_Re (x))) /*#G 27/4/98 */
364 d2 = 0.0; /*#G 27/4/98 */
365 else /*#G 27/4/98 */
366 d2 = 1.0 / (cplx_Re (x) * (1.0 + d1 * d1));
367 cplx_Re (x) = d2;
368 cplx_Im (x) = -d2 * d1;
369 }
370 else
371 {
372 d1 = cplx_Re (x) / cplx_Im (x);
373 if (DBL_MAX / (1.0 + d1 * d1) < fabs (cplx_Re (x))) /*#G 27/4/98 */
374 d2 = 0.0; /*#G 27/4/98 */
375 else /*#G 27/4/98 */
376 d2 = 1.0 / (cplx_Im (x) * (1.0 + d1 * d1));
377 cplx_Im (x) = -d2;
378 cplx_Re (x) = d2 * d1;
379 }
380 }
381
382 void
cplx_sqr_eq(cplx_t x)383 cplx_sqr_eq (cplx_t x)
384 /* x = x * x */
385 {
386 double d;
387
388 d = cplx_Re (x) * cplx_Re (x) - cplx_Im (x) * cplx_Im (x);
389 cplx_Im (x) *= 2.0 * cplx_Re (x);
390 cplx_Re (x) = d;
391 }
392
393 void
cplx_rot_eq(cplx_t x)394 cplx_rot_eq (cplx_t x)
395 /* x = I x */
396 {
397 double d;
398
399 d = cplx_Re (x);
400 cplx_Re (x) = -cplx_Im (x);
401 cplx_Im (x) = d;
402 }
403
404 void
cplx_flip_eq(cplx_t x)405 cplx_flip_eq (cplx_t x)
406 /* x = (Im(x), Re(x)) */
407 {
408 double d;
409
410 d = cplx_Re (x);
411 cplx_Re (x) = cplx_Im (x);
412 cplx_Im (x) = d;
413 }
414
415 void
cplx_add_eq(cplx_t rx,const cplx_t x)416 cplx_add_eq (cplx_t rx, const cplx_t x)
417 /* rx = rx + x */
418 {
419 cplx_Re (rx) += cplx_Re (x);
420 cplx_Im (rx) += cplx_Im (x);
421 }
422
423 void
cplx_sub_eq(cplx_t rx,const cplx_t x)424 cplx_sub_eq (cplx_t rx, const cplx_t x)
425 /* rx = rx - x */
426 {
427 cplx_Re (rx) -= cplx_Re (x);
428 cplx_Im (rx) -= cplx_Im (x);
429 }
430
431 void
cplx_mul_eq(cplx_t rx,const cplx_t x)432 cplx_mul_eq (cplx_t rx, const cplx_t x)
433 /* rx = rx * x */
434 {
435 double d;
436
437 d = cplx_Re (rx) * cplx_Re (x) - cplx_Im (rx) * cplx_Im (x);
438 cplx_Im (rx) = cplx_Im (rx) * cplx_Re (x) + cplx_Re (rx) * cplx_Im (x);
439 cplx_Re (rx) = d;
440 }
441
442 void
cplx_mul_eq_d(cplx_t x,double d)443 cplx_mul_eq_d (cplx_t x, double d)
444 /* x = x * d */
445 {
446 cplx_Re (x) *= d;
447 cplx_Im (x) *= d;
448 }
449
450 void
cplx_div_eq(cplx_t rx,const cplx_t x)451 cplx_div_eq (cplx_t rx, const cplx_t x)
452 /* rx = x1 / x2 */
453 {
454 cplx_t ctmp;
455
456 cplx_inv (ctmp, x);
457 cplx_mul_eq (rx, ctmp);
458 }
459
460 void
cplx_div_eq_d(cplx_t x,double d)461 cplx_div_eq_d (cplx_t x, double d)
462 /* x = x / d */
463 {
464 cplx_Re (x) /= d;
465 cplx_Im (x) /= d;
466 }
467
468 void
cplx_pow_eq_si(cplx_t x,register signed long int i)469 cplx_pow_eq_si (cplx_t x, register signed long int i)
470 /* x = x ^ i , i integer */
471 {
472 cplx_t t;
473
474 cplx_Move (t, x);
475 cplx_Move (x, cplx_one);
476
477 if (i < 0)
478 {
479 cplx_inv_eq (t);
480 i = -i;
481 }
482 while (i)
483 {
484 if (i & 1)
485 cplx_mul_eq (x, t);
486 cplx_sqr_eq (t);
487 i >>= 1; /* divide i by 2 */
488 }
489 }
490
491 /*------------ relational ops. -------------------------*/
492
493 int
cplx_eq_zero(const cplx_t x)494 cplx_eq_zero (const cplx_t x)
495 /* x == 0 */
496 {
497 return cplx_Re (x) == 0.0 && cplx_Im (x) == 0.0;
498 }
499
500 int
cplx_eq(const cplx_t x1,const cplx_t x2)501 cplx_eq (const cplx_t x1, const cplx_t x2)
502 /* x1 == x2 */
503 {
504 return cplx_Re (x1) == cplx_Re (x2) && cplx_Im (x1) == cplx_Im (x2);
505 }
506
507 int
cplx_ne(const cplx_t x1,const cplx_t x2)508 cplx_ne (const cplx_t x1, const cplx_t x2)
509 /* x1 != x2 */
510 {
511 return cplx_Re (x1) != cplx_Re (x2) || cplx_Im (x1) != cplx_Im (x2);
512 }
513
514 /*------------ vector functions ------------------------*/
515
516 void
cplx_vinit(cplx_t v[],long size)517 cplx_vinit (cplx_t v[], long size)
518 {
519 long i;
520
521 for (i = 0; i < size; i++)
522 cplx_Move (v[i], cplx_zero);
523 }
524
525 #else
526
527 const cplx_t cplx_zero = { 0.0 };
528 const cplx_t cplx_one = { 1.0 };
529 const cplx_t cplx_i = { 1.0I };
530
531 #endif
532
533 int
cplx_check_fpe(cplx_t c)534 cplx_check_fpe (cplx_t c)
535 /* Check if the components are NaN or Inf */
536 {
537 int fp = 0;
538
539 if (isnan (cplx_Re (c)))
540 fp += 1;
541 if (isnan (cplx_Im (c)))
542 fp += (1 << 1);
543 if (isinf (cplx_Re (c)))
544 fp += (1 << 2);
545 if (isinf (cplx_Im (c)))
546 fp += (1 << 3);
547 return fp;
548 }
549
550 /*------------ I/O functions ---------------------------*/
551
552 int
cplx_out_str_u(FILE * f,const cplx_t x)553 cplx_out_str_u (FILE * f, const cplx_t x)
554 /* output to file as re im */
555 {
556 if (f == NULL)
557 f = stdout;
558 return fprintf (f, CPLX_OUT_UFMT, cplx_Re (x), cplx_Im (x));
559 }
560
561 int
cplx_out_str(FILE * f,const cplx_t x)562 cplx_out_str (FILE * f, const cplx_t x)
563 /* output to file as (re, im) */
564 {
565 if (f == NULL)
566 f = stdout;
567 return fprintf (f, CPLX_OUT_FMT, cplx_Re (x), cplx_Im (x));
568 }
569
570 int
cplx_inp_str_u(cplx_t x,FILE * f)571 cplx_inp_str_u (cplx_t x, FILE * f)
572 /* input from file as (re, im) */
573 {
574 double real, imag;
575
576 if (f == NULL)
577 f = stdin;
578 int ret = fscanf (f, CPLX_INP_UFMT, &real, &imag);
579 cplx_set_d (x, real, imag);
580 return ret;
581 }
582
583 int
cplx_inp_str(cplx_t x,FILE * f)584 cplx_inp_str (cplx_t x, FILE * f)
585 /* input from file as (re, im) */
586 {
587 double real, imag;
588
589 if (f == NULL)
590 f = stdin;
591 int ret = fscanf (f, CPLX_INP_FMT, &real, &imag);
592 cplx_set_d (x, real, imag);
593 return ret;
594 }
595
596 /***********************************************************
597 ** functions for rdpe_t **
598 ***********************************************************/
599
600 /* normalize: mant(e) in [1/2, 1) */
601 #define rdpe_Norm(E) \
602 { \
603 int i; \
604 rdpe_Mnt (E) = frexp (rdpe_Mnt (E), &i); \
605 if (rdpe_Mnt (E) == 0.0) rdpe_Esp (E) = 0L; \
606 else rdpe_Esp (E) += i; \
607 }
608
609 /* constants */
610 const rdpe_t rdpe_zero = { { 0.0, 0L } };
611 const rdpe_t rdpe_one = { { 0.5, 1L } };
612 const rdpe_t RDPE_MAX = { { 0.5, LONG_MAX } };
613 const rdpe_t RDPE_MIN = { { 0.5, LONG_MIN } };
614 const rdpe_t rdpe_maxd = { { 0.5, DBL_MAX_EXP } };
615 const rdpe_t rdpe_mind = { { 0.5, DBL_MIN_EXP } };
616 const rdpe_t RDPE_BIG = { { 0.5, LONG_MAX >> 10 } };
617
618 void
rdpe_d(rdpe_t temp_rdpe,double d)619 rdpe_d (rdpe_t temp_rdpe, double d)
620 /* return d as a rdpe_t */
621 {
622 rdpe_Mnt (temp_rdpe) = d;
623 rdpe_Esp (temp_rdpe) = 0L;
624 rdpe_Norm (temp_rdpe);
625 }
626
627 void
rdpe_2dl(rdpe_t temp_rdpe,double d,long l)628 rdpe_2dl (rdpe_t temp_rdpe, double d, long l)
629 /* return d*2^l as a rdpe_t */
630 {
631 rdpe_Mnt (temp_rdpe) = d;
632 rdpe_Esp (temp_rdpe) = l;
633 rdpe_Norm (temp_rdpe);;
634 }
635
636 void
rdpe_clear(rdpe_t e)637 rdpe_clear (rdpe_t e)
638 /* e = 0 */
639 {
640 rdpe_Move (e, rdpe_zero);
641 }
642
643 void
rdpe_set(rdpe_t re,const rdpe_t e)644 rdpe_set (rdpe_t re, const rdpe_t e)
645 /* re = e */
646 {
647 rdpe_Move (re, e);
648 }
649
650 void
rdpe_set_dl(rdpe_t e,double d,long int l)651 rdpe_set_dl (rdpe_t e, double d, long int l)
652 /* e = d*10^l */
653 {
654 double x;
655
656 if (d == 0.0)
657 {
658 rdpe_Move (e, rdpe_zero);
659 return;
660 }
661 else if (d > 0.0)
662 {
663 rdpe_Mnt (e) = log (d) / LOG_2 + l * LOG2_10;
664 rdpe_Mnt (e) = pow (2.0, modf (rdpe_Mnt (e), &x));
665 }
666 else
667 { /* d < 0 */
668 rdpe_Mnt (e) = log (-d) / LOG_2 + l * LOG2_10;
669 rdpe_Mnt (e) = -pow (2.0, modf (rdpe_Mnt (e), &x));
670 }
671 rdpe_Esp (e) = (long int)x;
672 rdpe_Norm (e);
673 }
674
675 void
rdpe_set_2dl(rdpe_t e,double d,long int l)676 rdpe_set_2dl (rdpe_t e, double d, long int l)
677 /* e = d*2^l */
678 {
679 rdpe_Mnt (e) = d;
680 rdpe_Esp (e) = l;
681 rdpe_Norm (e);
682 }
683
684 void
rdpe_set_d(rdpe_t e,double d)685 rdpe_set_d (rdpe_t e, double d)
686 /* e = d */
687 {
688 rdpe_Mnt (e) = d;
689 rdpe_Esp (e) = 0L;
690 rdpe_Norm (e);
691 }
692
693 int
rdpe_set_str(rdpe_t e,const char * s)694 rdpe_set_str (rdpe_t e, const char *s)
695 /* input from string as mant x exp) */
696 {
697 if (sscanf (s, RDPE_INP_FMT, &rdpe_Mnt (e), &rdpe_Esp (e)) != 2)
698 return 0;
699 rdpe_set_dl (e, rdpe_Mnt (e), rdpe_Esp (e));
700 return 1;
701 }
702
703 void
rdpe_get_dl(double * d,long int * l,const rdpe_t e)704 rdpe_get_dl (double *d, long int *l, const rdpe_t e)
705 /* returns mantissa and exponent of e */
706 {
707 double x;
708
709 if (rdpe_Mnt (e) == 0.0)
710 {
711 *d = 0.0;
712 *l = 0L;
713 }
714 else if (rdpe_Mnt (e) > 0)
715 {
716 *d = log10 (rdpe_Mnt (e)) + rdpe_Esp (e) * LOG10_2;
717 *d = pow (10.0, modf (*d, &x));
718 *l = (long int)x;
719 }
720 else
721 { /* rdpe_Mnt(e) > 0 */
722 *d = log10 (-rdpe_Mnt (e)) + rdpe_Esp (e) * LOG10_2;
723 *d = -pow (10.0, modf (*d, &x));
724 *l = (long int)x;
725 }
726 }
727
728 void
rdpe_get_2dl(double * d,long int * l,const rdpe_t e)729 rdpe_get_2dl (double *d, long int *l, const rdpe_t e)
730 /* returns mantissa and exponent of e in base 2 */
731 {
732 *d = rdpe_Mnt (e);
733 *l = rdpe_Esp (e);
734 }
735
736 double
rdpe_get_d(const rdpe_t e)737 rdpe_get_d (const rdpe_t e)
738 {
739 return ldexp (rdpe_Mnt (e), (int)rdpe_Esp (e));
740 }
741
742 char *
rdpe_get_str(char * s,const rdpe_t e)743 rdpe_get_str (char *s, const rdpe_t e)
744 /* output to string */
745 {
746 double d;
747 long int l;
748
749 if (s == NULL && (s = (char*)mps_malloc (DEF_STR_SIZE)) == NULL)
750 return NULL;
751 rdpe_get_dl (&d, &l, e);
752 sprintf (s, RDPE_OUT_FMT, d, l);
753 return s;
754 }
755
756 void
rdpe_neg(rdpe_t re,const rdpe_t e)757 rdpe_neg (rdpe_t re, const rdpe_t e)
758 /* re = -e */
759 {
760 rdpe_Mnt (re) = -rdpe_Mnt (e);
761 rdpe_Esp (re) = rdpe_Esp (e);
762 }
763
764 void
rdpe_abs(rdpe_t re,const rdpe_t e)765 rdpe_abs (rdpe_t re, const rdpe_t e)
766 /* re = |e| */
767 {
768 rdpe_Mnt (re) = (rdpe_Mnt (e) > 0) ? rdpe_Mnt (e) : -rdpe_Mnt (e);
769 rdpe_Esp (re) = rdpe_Esp (e);
770 }
771
772 void
rdpe_inv(rdpe_t re,const rdpe_t e)773 rdpe_inv (rdpe_t re, const rdpe_t e)
774 /* re = 1 / e */
775 {
776 rdpe_Mnt (re) = 1.0 / rdpe_Mnt (e);
777 rdpe_Esp (re) = -rdpe_Esp (e);
778 rdpe_Norm (re);
779 }
780
781 void
rdpe_sqr(rdpe_t re,const rdpe_t e)782 rdpe_sqr (rdpe_t re, const rdpe_t e)
783 /* re = e * e */
784 {
785 rdpe_Mnt (re) = rdpe_Mnt (e) * rdpe_Mnt (e);
786 rdpe_Esp (re) = rdpe_Esp (e) + rdpe_Esp (e);
787 rdpe_Norm (re);
788 }
789
790 void
rdpe_sqrt(rdpe_t re,const rdpe_t e)791 rdpe_sqrt (rdpe_t re, const rdpe_t e)
792 /* re = e^(1/2) */
793 {
794 if (rdpe_Esp (e) & 1)
795 {
796 rdpe_Mnt (re) = sqrt (rdpe_Mnt (e) / 2.0);
797 rdpe_Esp (re) = (rdpe_Esp (e) + 1) / 2;
798 }
799 else
800 {
801 rdpe_Mnt (re) = sqrt (rdpe_Mnt (e));
802 rdpe_Esp (re) = rdpe_Esp (e) / 2;
803 }
804 rdpe_Norm (re);
805 }
806
807 double
rdpe_log(const rdpe_t e)808 rdpe_log (const rdpe_t e)
809 /* returns log(e) */
810 {
811 return log (rdpe_Mnt (e)) + rdpe_Esp (e) * LOG_2;
812 }
813
814 double
rdpe_log10(const rdpe_t e)815 rdpe_log10 (const rdpe_t e)
816 /* returns log10(e) */
817 {
818 return (log (rdpe_Mnt (e)) + rdpe_Esp (e) * LOG_2) / LOG_10;
819 }
820
821 void
rdpe_exp(rdpe_t re,const rdpe_t e)822 rdpe_exp (rdpe_t re, const rdpe_t e)
823 /* re = E^(e) */
824 {
825 long int i;
826
827 i = rdpe_Esp (e);
828 rdpe_set_2dl (re, exp (rdpe_Mnt (e)), 0L);
829
830 if (i >= 0)
831 while (i > 0)
832 {
833 rdpe_sqr_eq (re);
834 i--;
835 }
836 else
837 while (i < 0)
838 {
839 rdpe_sqrt_eq (re);
840 i++;
841 }
842 }
843
844 void
rdpe_mul(rdpe_t re,const rdpe_t e1,const rdpe_t e2)845 rdpe_mul (rdpe_t re, const rdpe_t e1, const rdpe_t e2)
846 /* re = e1 * e2 */
847 {
848 if (rdpe_Esp (e1) >= 0 && (rdpe_Esp (e2) >= LONG_MAX - rdpe_Esp (e1)))
849 {
850 rdpe_set (re, RDPE_MAX);
851 return;
852 }
853 if (rdpe_Esp (e1) <= 0 && (rdpe_Esp (e2) <= LONG_MIN - rdpe_Esp (e1)))
854 {
855 rdpe_set (re, RDPE_MAX);
856 return;
857 }
858 rdpe_Mnt (re) = rdpe_Mnt (e1) * rdpe_Mnt (e2);
859 rdpe_Esp (re) = rdpe_Esp (e1) + rdpe_Esp (e2);
860 rdpe_Norm (re);
861 }
862
863 void
rdpe_mul_d(rdpe_t re,const rdpe_t e,double d)864 rdpe_mul_d (rdpe_t re, const rdpe_t e, double d)
865 /* re = e * d */
866 {
867 int esp;
868
869 frexp (d, &esp);
870 if (rdpe_Esp (e) >= 0 && (esp >= LONG_MAX - rdpe_Esp (e)))
871 {
872 rdpe_set (re, RDPE_MAX);
873 return;
874 }
875 if (rdpe_Esp (e) <= 0 && (esp <= LONG_MIN - rdpe_Esp (e)))
876 {
877 rdpe_set (re, RDPE_MAX);
878 return;
879 }
880 rdpe_Mnt (re) = rdpe_Mnt (e) * d;
881 rdpe_Esp (re) = rdpe_Esp (e);
882 rdpe_Norm (re);
883 }
884
885 void
rdpe_mul_2exp(rdpe_t re,const rdpe_t e,unsigned long int i)886 rdpe_mul_2exp (rdpe_t re, const rdpe_t e, unsigned long int i)
887 /* re = e * 2^i */
888 {
889 rdpe_Mnt (re) = rdpe_Mnt (e);
890 rdpe_Esp (re) = rdpe_Esp (e) + i;
891 }
892
893 void
rdpe_div(rdpe_t re,const rdpe_t e1,const rdpe_t e2)894 rdpe_div (rdpe_t re, const rdpe_t e1, const rdpe_t e2)
895 /* re = e1 / e2 */
896 {
897 rdpe_Mnt (re) = rdpe_Mnt (e1) / rdpe_Mnt (e2);
898 rdpe_Esp (re) = rdpe_Esp (e1) - rdpe_Esp (e2);
899 rdpe_Norm (re);
900 }
901
902 void
rdpe_div_d(rdpe_t re,const rdpe_t e,double d)903 rdpe_div_d (rdpe_t re, const rdpe_t e, double d)
904 /* re = e / d */
905 {
906 rdpe_Mnt (re) = rdpe_Mnt (e) / d;
907 rdpe_Esp (re) = rdpe_Esp (e);
908 rdpe_Norm (re);
909 }
910
911 void
rdpe_div_2exp(rdpe_t re,const rdpe_t e,unsigned long int i)912 rdpe_div_2exp (rdpe_t re, const rdpe_t e, unsigned long int i)
913 /* re = e / 2^i */
914 {
915 rdpe_Mnt (re) = rdpe_Mnt (e);
916 rdpe_Esp (re) = rdpe_Esp (e) - i;
917 }
918
919 void
rdpe_add(rdpe_t re,const rdpe_t e1,const rdpe_t e2)920 rdpe_add (rdpe_t re, const rdpe_t e1, const rdpe_t e2)
921 /* re = e1 + e2 */
922 {
923 long delta;
924
925 /* Check for overflows */
926 if (rdpe_Mnt (e1) > 0 && rdpe_Mnt (e2) > 0 && rdpe_Esp (e1) == LONG_MAX && rdpe_Esp (e2) == LONG_MAX)
927 {
928 rdpe_set (re, RDPE_MAX);
929 return;
930 }
931 if (rdpe_Mnt (e1) < 0 && rdpe_Mnt (e2) < 0 && rdpe_Esp (e1) == LONG_MAX && rdpe_Esp (e2) == LONG_MAX)
932 {
933 rdpe_set_dl (re, -0.5, LONG_MAX);
934 return;
935 }
936
937 if (rdpe_Mnt (e2) == 0.0)
938 {
939 rdpe_Move (re, e1);
940 return;
941 }
942 if (rdpe_Mnt (e1) == 0.0)
943 {
944 rdpe_Move (re, e2);
945 return;
946 }
947 delta = rdpe_Esp (e1) - rdpe_Esp (e2);
948
949 if (delta > NBT)
950 rdpe_Move (re, e1);
951 else if (delta < -NBT)
952 rdpe_Move (re, e2);
953 else if (delta == 0)
954 {
955 rdpe_Mnt (re) = rdpe_Mnt (e1) + rdpe_Mnt (e2);
956 rdpe_Esp (re) = rdpe_Esp (e1);
957 rdpe_Norm (re);
958 }
959 else if (delta > 0)
960 {
961 rdpe_Mnt (re) = rdpe_Mnt (e1) + ldexp (rdpe_Mnt (e2), (int)-delta);
962 rdpe_Esp (re) = rdpe_Esp (e1);
963 rdpe_Norm (re);
964 }
965 else
966 { /* delta < 0 */
967 rdpe_Mnt (re) = ldexp (rdpe_Mnt (e1), (int)delta) + rdpe_Mnt (e2);
968 rdpe_Esp (re) = rdpe_Esp (e2);
969 rdpe_Norm (re);
970 }
971 }
972
973 void
rdpe_sub(rdpe_t re,const rdpe_t e1,const rdpe_t e2)974 rdpe_sub (rdpe_t re, const rdpe_t e1, const rdpe_t e2)
975 /* re = e1 - e2 */
976 {
977 long delta;
978
979 if (rdpe_Mnt (e2) == 0.0)
980 {
981 rdpe_Move (re, e1);
982 return;
983 }
984 if (rdpe_Mnt (e1) == 0.0)
985 {
986 rdpe_Mnt (re) = -rdpe_Mnt (e2);
987 rdpe_Esp (re) = rdpe_Esp (e2);
988 return;
989 }
990
991 delta = rdpe_Esp (e1) - rdpe_Esp (e2);
992
993 if (delta > NBT)
994 rdpe_Move (re, e1);
995 else if (delta < -NBT)
996 {
997 rdpe_Mnt (re) = -rdpe_Mnt (e2);
998 rdpe_Esp (re) = rdpe_Esp (e2);
999 }
1000 else if (delta == 0)
1001 {
1002 rdpe_Mnt (re) = rdpe_Mnt (e1) - rdpe_Mnt (e2);
1003 rdpe_Esp (re) = rdpe_Esp (e1);
1004 rdpe_Norm (re);
1005 }
1006 else if (delta > 0)
1007 {
1008 rdpe_Mnt (re) = rdpe_Mnt (e1) - ldexp (rdpe_Mnt (e2), (int)-delta);
1009 rdpe_Esp (re) = rdpe_Esp (e1);
1010 rdpe_Norm (re);
1011 }
1012 else
1013 { /* delta < 0 */
1014 rdpe_Mnt (re) = ldexp (rdpe_Mnt (e1), (int)delta) - rdpe_Mnt (e2);
1015 rdpe_Esp (re) = rdpe_Esp (e2);
1016 rdpe_Norm (re);
1017 }
1018 }
1019
1020 void
rdpe_add_d(rdpe_t re,const rdpe_t e,double d)1021 rdpe_add_d (rdpe_t re, const rdpe_t e, double d)
1022 /* re = e + d */
1023 {
1024 rdpe_t t;
1025
1026 rdpe_set_d (t, d);
1027 rdpe_add (re, e, t);
1028 }
1029
1030 void
rdpe_sub_d(rdpe_t re,const rdpe_t e,double d)1031 rdpe_sub_d (rdpe_t re, const rdpe_t e, double d)
1032 /* re = e - d */
1033 {
1034 rdpe_t t;
1035
1036 rdpe_set_d (t, d);
1037 rdpe_sub (re, e, t);
1038 }
1039
1040 void
rdpe_pow_d(rdpe_t re,const rdpe_t e,double d)1041 rdpe_pow_d (rdpe_t re, const rdpe_t e, double d)
1042 /* re = e ^ d */
1043 {
1044 double a, i, f;
1045
1046 a = d * (log (rdpe_Mnt (e)) / LOG_2 + rdpe_Esp (e));
1047 f = modf (a, &i);
1048 rdpe_set_2dl (re, exp (f * LOG_2), (long)i);
1049 }
1050
1051 void
rdpe_pow_d2(rdpe_t re,const rdpe_t e,double d)1052 rdpe_pow_d2 (rdpe_t re, const rdpe_t e, double d)
1053 /* re = e ^ d, d double */
1054 {
1055 double a, i;
1056
1057 a = pow (rdpe_Mnt (e), d);
1058 a *= pow (2.0, modf (rdpe_Esp (e) * d, &i));
1059 rdpe_set_2dl (re, a, (long)i);
1060 }
1061
1062 void
rdpe_pow_si(rdpe_t re,const rdpe_t e,register signed long int i)1063 rdpe_pow_si (rdpe_t re, const rdpe_t e, register signed long int i)
1064 /* re = e ^ i, i integer */
1065 {
1066 rdpe_t t;
1067
1068 rdpe_Move (t, e);
1069 rdpe_Move (re, rdpe_one);
1070
1071 if (i < 0)
1072 {
1073 rdpe_inv (t, t);
1074 i = -i;
1075 }
1076 while (i)
1077 {
1078 if (i & 1)
1079 rdpe_mul_eq (re, t);
1080 rdpe_sqr_eq (t);
1081 i >>= 1; /* divide i by 2 */
1082 }
1083 }
1084
1085 void
rdpe_swap(rdpe_t e1,rdpe_t e2)1086 rdpe_swap (rdpe_t e1, rdpe_t e2)
1087 /* e1 <-> e2 */
1088 {
1089 rdpe_t t;
1090
1091 rdpe_Move (t, e1);
1092 rdpe_Move (e1, e2);
1093 rdpe_Move (e2, t);
1094 }
1095
1096 void
rdpe_neg_eq(rdpe_t e)1097 rdpe_neg_eq (rdpe_t e)
1098 /* e = -e */
1099 {
1100 rdpe_Mnt (e) = -rdpe_Mnt (e);
1101 rdpe_Esp (e) = rdpe_Esp (e);
1102 }
1103
1104 void
rdpe_abs_eq(rdpe_t e)1105 rdpe_abs_eq (rdpe_t e)
1106 /* e = |e| */
1107 {
1108 rdpe_Mnt (e) = (rdpe_Mnt (e) > 0) ? rdpe_Mnt (e) : -rdpe_Mnt (e);
1109 }
1110
1111 void
rdpe_inv_eq(rdpe_t e)1112 rdpe_inv_eq (rdpe_t e)
1113 /* e = 1 / e */
1114 {
1115 rdpe_Mnt (e) = 1.0 / rdpe_Mnt (e);
1116 rdpe_Esp (e) = -rdpe_Esp (e);
1117 rdpe_Norm (e);
1118 }
1119
1120 void
rdpe_sqr_eq(rdpe_t e)1121 rdpe_sqr_eq (rdpe_t e)
1122 /* e = e * e */
1123 {
1124 rdpe_Mnt (e) *= rdpe_Mnt (e);
1125 rdpe_Esp (e) <<= 1; /* multiply by 2 */
1126 rdpe_Norm (e);
1127 }
1128
1129 void
rdpe_sqrt_eq(rdpe_t e)1130 rdpe_sqrt_eq (rdpe_t e)
1131 /* e = e^(1/2) */
1132 {
1133 if (rdpe_Esp (e) & 1)
1134 { /* odd test */
1135 rdpe_Mnt (e) = sqrt (rdpe_Mnt (e) / 2.0);
1136 rdpe_Esp (e) = (rdpe_Esp (e) + 1) / 2;
1137 }
1138 else
1139 {
1140 rdpe_Mnt (e) = sqrt (rdpe_Mnt (e));
1141 rdpe_Esp (e) /= 2;
1142 }
1143 rdpe_Norm (e);
1144 }
1145
1146 void
rdpe_exp_eq(rdpe_t e)1147 rdpe_exp_eq (rdpe_t e)
1148 /* re = E^(e) */
1149 {
1150 long int i;
1151
1152 i = rdpe_Esp (e);
1153 rdpe_set_2dl (e, exp (rdpe_Mnt (e)), 0L);
1154
1155 if (i >= 0)
1156 while (i > 0)
1157 {
1158 rdpe_sqr_eq (e);
1159 i--;
1160 }
1161 else
1162 while (i < 0)
1163 {
1164 rdpe_sqrt_eq (e);
1165 i++;
1166 }
1167 }
1168
1169 void
rdpe_mul_eq(rdpe_t re,const rdpe_t e)1170 rdpe_mul_eq (rdpe_t re, const rdpe_t e)
1171 /* re = re * e */
1172 {
1173 ;
1174 if (rdpe_Esp (re) >= 0 && (rdpe_Esp (e) >= LONG_MAX - rdpe_Esp (re)))
1175 {
1176 rdpe_set (re, RDPE_MAX);
1177 return;
1178 }
1179 if (rdpe_Esp (re) <= 0 && (rdpe_Esp (e) <= LONG_MIN - rdpe_Esp (re)))
1180 {
1181 rdpe_set (re, RDPE_MAX);
1182 return;
1183 }
1184 rdpe_Mnt (re) *= rdpe_Mnt (e);
1185 rdpe_Esp (re) += rdpe_Esp (e);
1186 rdpe_Norm (re);
1187 }
1188
1189 void
rdpe_mul_eq_d(rdpe_t e,double d)1190 rdpe_mul_eq_d (rdpe_t e, double d)
1191 /* e = e * d */
1192 {
1193 int esp;
1194
1195 frexp (d, &esp);
1196 if (rdpe_Esp (e) >= 0 && (esp >= LONG_MAX - rdpe_Esp (e)))
1197 {
1198 rdpe_set (e, RDPE_MAX);
1199 return;
1200 }
1201 if (rdpe_Esp (e) <= 0 && (esp <= LONG_MIN - rdpe_Esp (e)))
1202 {
1203 rdpe_set (e, RDPE_MAX);
1204 return;
1205 }
1206 rdpe_Mnt (e) *= d;
1207 rdpe_Norm (e);
1208 }
1209
1210 void
rdpe_mul_eq_2exp(rdpe_t e,unsigned long int i)1211 rdpe_mul_eq_2exp (rdpe_t e, unsigned long int i)
1212 /* e = e * 2^i */
1213 {
1214 rdpe_Esp (e) += i;
1215 }
1216
1217 void
rdpe_div_eq(rdpe_t re,const rdpe_t e)1218 rdpe_div_eq (rdpe_t re, const rdpe_t e)
1219 /* re = re / e */
1220 {
1221 rdpe_Mnt (re) /= rdpe_Mnt (e);
1222 rdpe_Esp (re) -= rdpe_Esp (e);
1223 rdpe_Norm (re);
1224 }
1225
1226 void
rdpe_div_eq_d(rdpe_t e,double d)1227 rdpe_div_eq_d (rdpe_t e, double d)
1228 /* e = e / d */
1229 {
1230 rdpe_Mnt (e) /= d;
1231 rdpe_Norm (e);
1232 }
1233
1234 void
rdpe_div_eq_2exp(rdpe_t e,unsigned long int i)1235 rdpe_div_eq_2exp (rdpe_t e, unsigned long int i)
1236 /* e = e / 2^i */
1237 {
1238 rdpe_Esp (e) -= i;
1239 }
1240
1241 void
rdpe_add_eq(rdpe_t re,const rdpe_t e)1242 rdpe_add_eq (rdpe_t re, const rdpe_t e)
1243 /* re = re + e */
1244 {
1245 long int delta;
1246
1247 if (rdpe_Mnt (e) == 0.0)
1248 return;
1249 if (rdpe_Mnt (re) == 0.0)
1250 {
1251 rdpe_Move (re, e);
1252 return;
1253 }
1254 delta = rdpe_Esp (re) - rdpe_Esp (e);
1255
1256 if (delta > NBT)
1257 return;
1258 else if (delta < -NBT)
1259 rdpe_Move (re, e);
1260 else if (delta == 0)
1261 {
1262 rdpe_Mnt (re) += rdpe_Mnt (e);
1263 rdpe_Norm (re);
1264 }
1265 else if (delta > 0)
1266 {
1267 rdpe_Mnt (re) += ldexp (rdpe_Mnt (e), (int)-delta);
1268 rdpe_Norm (re);
1269 }
1270 else
1271 { /* delta < 0 */
1272 rdpe_Mnt (re) = ldexp (rdpe_Mnt (re), (int)delta) + rdpe_Mnt (e);
1273 rdpe_Esp (re) = rdpe_Esp (e);
1274 rdpe_Norm (re);
1275 }
1276 }
1277
1278 void
rdpe_sub_eq(rdpe_t re,const rdpe_t e)1279 rdpe_sub_eq (rdpe_t re, const rdpe_t e)
1280 /* re = re - e */
1281 {
1282 long int delta;
1283
1284 if (rdpe_Mnt (e) == 0.0)
1285 return;
1286 if (rdpe_Mnt (re) == 0.0)
1287 {
1288 rdpe_Mnt (re) = -rdpe_Mnt (e);
1289 rdpe_Esp (re) = rdpe_Esp (e);
1290 return;
1291 }
1292 delta = rdpe_Esp (re) - rdpe_Esp (e);
1293
1294 if (delta > NBT)
1295 return;
1296 else if (delta < -NBT)
1297 {
1298 rdpe_Mnt (re) = -rdpe_Mnt (e);
1299 rdpe_Esp (re) = rdpe_Esp (e);
1300 }
1301 else if (delta == 0)
1302 {
1303 rdpe_Mnt (re) -= rdpe_Mnt (e);
1304 rdpe_Norm (re);
1305 }
1306 else if (delta > 0)
1307 {
1308 rdpe_Mnt (re) -= ldexp (rdpe_Mnt (e), (int)-delta);
1309 rdpe_Norm (re);
1310 }
1311 else
1312 { /* delta < 0 */
1313 rdpe_Mnt (re) = ldexp (rdpe_Mnt (re), (int)delta) - rdpe_Mnt (e);
1314 rdpe_Esp (re) = rdpe_Esp (e);
1315 rdpe_Norm (re);
1316 }
1317 }
1318
1319 void
rdpe_add_eq_d(rdpe_t e,double d)1320 rdpe_add_eq_d (rdpe_t e, double d)
1321 /* re = e + d */
1322 {
1323 rdpe_t t;
1324
1325 rdpe_set_d (t, d);
1326 rdpe_add_eq (e, t);
1327 }
1328
1329 void
rdpe_sub_eq_d(rdpe_t e,double d)1330 rdpe_sub_eq_d (rdpe_t e, double d)
1331 /* re = e - d */
1332 {
1333 rdpe_t t;
1334
1335 rdpe_set_d (t, d);
1336 rdpe_sub_eq (e, t);
1337 }
1338
1339 void
rdpe_pow_eq_d(rdpe_t e,double d)1340 rdpe_pow_eq_d (rdpe_t e, double d)
1341 /* re = e ^ d */
1342 {
1343 double a, i, f;
1344
1345 a = d * (log (rdpe_Mnt (e)) / LOG_2 + rdpe_Esp (e));
1346 f = modf (a, &i);
1347 rdpe_set_2dl (e, exp (f * LOG_2), (long)i);
1348 }
1349
1350 void
rdpe_pow_eq_si(rdpe_t e,register signed long int i)1351 rdpe_pow_eq_si (rdpe_t e, register signed long int i)
1352 /* e = e ^ i, i integer */
1353 {
1354 rdpe_t t;
1355
1356 rdpe_Move (t, e);
1357 rdpe_Move (e, rdpe_one);
1358
1359 if (i < 0)
1360 {
1361 rdpe_inv (t, t);
1362 i = -i;
1363 }
1364 while (i)
1365 {
1366 if (i & 1)
1367 rdpe_mul_eq (e, t);
1368 rdpe_sqr_eq (t);
1369 i >>= 1; /* divide i by 2 */
1370 }
1371 }
1372
1373 void
rdpe_fac_ui(rdpe_t e,register unsigned long int n)1374 rdpe_fac_ui (rdpe_t e, register unsigned long int n)
1375 /* e = n! */
1376 {
1377 rdpe_Move (e, rdpe_one);
1378 while (n > 1)
1379 {
1380 rdpe_mul_eq_d (e, (double)n);
1381 n--;
1382 }
1383 }
1384
1385 /*------------ relational ops. -------------------------*/
1386
1387 int
rdpe_cmp(const rdpe_t e1,const rdpe_t e2)1388 rdpe_cmp (const rdpe_t e1, const rdpe_t e2)
1389 /* e1 <!> e2 */
1390 {
1391 rdpe_t t;
1392
1393 rdpe_sub (t, e1, e2);
1394 if (rdpe_Mnt (t) > 0.0)
1395 return 1;
1396 if (rdpe_Mnt (t) < 0.0)
1397 return -1;
1398 return 0;
1399 }
1400
1401 int
rdpe_sgn(const rdpe_t e)1402 rdpe_sgn (const rdpe_t e)
1403 /* sign(e) */
1404 {
1405 if (rdpe_Mnt (e) > 0.0)
1406 return 1;
1407 if (rdpe_Mnt (e) < 0.0)
1408 return -1;
1409 return 0;
1410 }
1411
1412 int
rdpe_eq_zero(const rdpe_t e)1413 rdpe_eq_zero (const rdpe_t e)
1414 /* e == 0 */
1415 {
1416 return rdpe_Mnt (e) == 0.0 && rdpe_Esp (e) == 0;
1417 }
1418
1419 int
rdpe_eq(const rdpe_t e1,const rdpe_t e2)1420 rdpe_eq (const rdpe_t e1, const rdpe_t e2)
1421 /* e1 == e2 */
1422 {
1423 return rdpe_Mnt (e1) == rdpe_Mnt (e2) && rdpe_Esp (e1) == rdpe_Esp (e2);
1424 }
1425
1426 int
rdpe_ne(const rdpe_t e1,const rdpe_t e2)1427 rdpe_ne (const rdpe_t e1, const rdpe_t e2)
1428 /* e1 != e2 */
1429 {
1430 return rdpe_Mnt (e1) != rdpe_Mnt (e2) || rdpe_Esp (e1) != rdpe_Esp (e2);
1431 }
1432
1433 int
rdpe_lt(const rdpe_t e1,const rdpe_t e2)1434 rdpe_lt (const rdpe_t e1, const rdpe_t e2)
1435 /* e1 < e2 */
1436 {
1437 rdpe_t t;
1438
1439 if (rdpe_Mnt (e1) > 0 && rdpe_Mnt (e2) < 0)
1440 return 1;
1441 if (rdpe_Mnt (e1) < 0 && rdpe_Mnt (e1) > 0)
1442 return 0;
1443
1444 /* This check works only if the numbers are non zero */
1445 if (rdpe_Mnt (e1) != 0 && rdpe_Mnt (e2) != 0)
1446 {
1447 if (rdpe_Esp (e1) > rdpe_Esp (e2))
1448 return 0;
1449 if (rdpe_Esp (e2) > rdpe_Esp (e1))
1450 return 1;
1451 }
1452
1453 rdpe_sub (t, e1, e2);
1454 return rdpe_Mnt (t) < 0.0;
1455 }
1456
1457 int
rdpe_le(const rdpe_t e1,const rdpe_t e2)1458 rdpe_le (const rdpe_t e1, const rdpe_t e2)
1459 /* e1 <= e2 */
1460 {
1461 rdpe_t t;
1462
1463 if (rdpe_Mnt (e1) > 0 && rdpe_Mnt (e2) < 0)
1464 return 1;
1465 if (rdpe_Mnt (e1) < 0 && rdpe_Mnt (e1) > 0)
1466 return 0;
1467
1468 /* This check works only if the numbers are non zero */
1469 if (rdpe_Mnt (e1) != 0 && rdpe_Mnt (e2) != 0)
1470 {
1471 if (rdpe_Esp (e1) > rdpe_Esp (e2))
1472 return 0;
1473 if (rdpe_Esp (e2) > rdpe_Esp (e1))
1474 return 1;
1475 }
1476
1477 rdpe_sub (t, e1, e2);
1478 return rdpe_Mnt (t) <= 0.0;
1479 }
1480
1481 int
rdpe_gt(const rdpe_t e1,const rdpe_t e2)1482 rdpe_gt (const rdpe_t e1, const rdpe_t e2)
1483 /* e1 > e2 */
1484 {
1485 rdpe_t t;
1486
1487 if (rdpe_Mnt (e1) > 0 && rdpe_Mnt (e2) < 0)
1488 return 0;
1489 if (rdpe_Mnt (e1) < 0 && rdpe_Mnt (e1) > 0)
1490 return 1;
1491
1492 /* This check works only if both DPE are non zero */
1493 if (rdpe_Mnt (e1) != 0 && rdpe_Mnt (e2) != 0)
1494 {
1495 if (rdpe_Esp (e1) > rdpe_Esp (e2))
1496 return 1;
1497 if (rdpe_Esp (e2) > rdpe_Esp (e1))
1498 return 0;
1499 }
1500
1501 rdpe_sub (t, e1, e2);
1502 return rdpe_Mnt (t) > 0.0;
1503 }
1504
1505 int
rdpe_ge(const rdpe_t e1,const rdpe_t e2)1506 rdpe_ge (const rdpe_t e1, const rdpe_t e2)
1507 /* e1 >= e2 */
1508 {
1509 rdpe_t t;
1510
1511 if (rdpe_Mnt (e1) > 0 && rdpe_Mnt (e2) < 0)
1512 return 0;
1513 if (rdpe_Mnt (e1) < 0 && rdpe_Mnt (e1) > 0)
1514 return 1;
1515
1516 /* This check works only if both DPE are non zero */
1517 if (rdpe_Mnt (e1) != 0 && rdpe_Mnt (e2) != 0)
1518 {
1519 if (rdpe_Esp (e1) > rdpe_Esp (e2))
1520 return 1;
1521 if (rdpe_Esp (e2) > rdpe_Esp (e1))
1522 return 0;
1523 }
1524
1525 rdpe_sub (t, e1, e2);
1526 return rdpe_Mnt (t) >= 0.0;
1527 }
1528
1529 /*------------ I/O functions ---------------------------*/
1530
1531 int
rdpe_out_str_u(FILE * f,const rdpe_t e)1532 rdpe_out_str_u (FILE * f, const rdpe_t e)
1533 /* output as mantissa e exponent, base 10 */
1534 {
1535 double d;
1536 long int l;
1537
1538 if (f == NULL)
1539 f = stdout;
1540 rdpe_get_dl (&d, &l, e);
1541 return fprintf (f, RDPE_OUT_UFMT, d, l);
1542 }
1543
1544 int
rdpe_out_str(FILE * f,const rdpe_t e)1545 rdpe_out_str (FILE * f, const rdpe_t e)
1546 /* output as mantissa x exponent, base 10 */
1547 {
1548 double d;
1549 long int l;
1550
1551 if (f == NULL)
1552 f = stdout;
1553 rdpe_get_dl (&d, &l, e);
1554 return fprintf (f, RDPE_OUT_FMT, d, l);
1555 }
1556
1557 int
rdpe_inp_str_u(rdpe_t e,FILE * f)1558 rdpe_inp_str_u (rdpe_t e, FILE * f)
1559 /* input from file as mant e exp */
1560 {
1561 double d;
1562 long int l;
1563
1564 if (f == NULL)
1565 f = stdin;
1566 if (fscanf (f, RDPE_INP_UFMT, &d, &l) != 2)
1567 return 0;
1568 rdpe_set_dl (e, d, l);
1569 return 1;
1570 }
1571
1572 int
rdpe_inp_str(rdpe_t e,FILE * f)1573 rdpe_inp_str (rdpe_t e, FILE * f)
1574 /* input from file as mant x exp */
1575 {
1576 double d;
1577 long int l;
1578
1579 if (f == NULL)
1580 f = stdin;
1581 if (fscanf (f, RDPE_INP_FMT, &d, &l) != 2)
1582 return 0;
1583 rdpe_set_dl (e, d, l);
1584 return 1;
1585 }
1586
1587 int
rdpe_inp_str_flex(rdpe_t e,FILE * f)1588 rdpe_inp_str_flex (rdpe_t e, FILE * f)
1589 /* More flexible input for rdpe */
1590 {
1591 double d;
1592 long int l = 0;
1593
1594 if (f == NULL)
1595 f = stdin;
1596
1597 if (fscanf (f, RDPE_INP_FMT, &d, &l) < 1)
1598 return 0;
1599 rdpe_set_dl (e, d, l);
1600 return 1;
1601 }
1602
1603 int
rdpe_inp_sstr_flex(rdpe_t e,char * f)1604 rdpe_inp_sstr_flex (rdpe_t e, char *f)
1605 /* More flexible input for rdpe */
1606 {
1607 double d;
1608 long int l = 0;
1609
1610 if (sscanf (f, RDPE_INP_FMT, &d, &l) < 1)
1611 return 0;
1612 rdpe_set_dl (e, d, l);
1613 return 1;
1614 }
1615
1616 /*------------ vector functions ------------------------*/
1617
1618 void
rdpe_vinit(rdpe_t v[],long size)1619 rdpe_vinit (rdpe_t v[], long size)
1620 {
1621 long i;
1622
1623 for (i = 0; i < size; i++)
1624 rdpe_Move (v[i], rdpe_zero);
1625 }
1626
1627 void
gdpe_add(gdpe_t res,gdpe_t g1,gdpe_t g2)1628 gdpe_add (gdpe_t res, gdpe_t g1, gdpe_t g2)
1629 {
1630 rdpe_add (gdpe_Val (res), gdpe_Val (g1), gdpe_Val (g2));
1631 rdpe_add (gdpe_Eps (res), gdpe_Eps (g1), gdpe_Eps (g2));
1632 gdpe_update_rel_from_abs (res);
1633 }
1634
1635 void
gdpe_sub(gdpe_t res,gdpe_t g1,gdpe_t g2)1636 gdpe_sub (gdpe_t res, gdpe_t g1, gdpe_t g2)
1637 {
1638 rdpe_sub (gdpe_Val (res), gdpe_Val (g1), gdpe_Val (g2));
1639 rdpe_add (gdpe_Eps (res), gdpe_Eps (g1), gdpe_Eps (g2));
1640 gdpe_update_rel_from_abs (res);
1641 }
1642
1643 void
gdpe_mul(gdpe_t res,gdpe_t g1,gdpe_t g2)1644 gdpe_mul (gdpe_t res, gdpe_t g1, gdpe_t g2)
1645 {
1646 rdpe_mul (gdpe_Val (res), gdpe_Val (g1), gdpe_Val (g2));
1647 if (gdpe_eq_zero (g1) || gdpe_eq_zero (g2))
1648 {
1649 rdpe_set (gdpe_Eps (res), rdpe_zero);
1650 return;
1651 }
1652
1653 rdpe_add (gdpe_Rel (res), gdpe_Rel (g1), gdpe_Rel (g2));
1654 gdpe_update_abs_from_rel (res);
1655 }
1656
1657 void
gdpe_div(gdpe_t res,gdpe_t g1,gdpe_t g2)1658 gdpe_div (gdpe_t res, gdpe_t g1, gdpe_t g2)
1659 {
1660 rdpe_div (gdpe_Val (res), gdpe_Val (g1), gdpe_Val (g2));
1661 if (gdpe_eq_zero (g1))
1662 {
1663 rdpe_set (gdpe_Eps (res), rdpe_zero);
1664 return;
1665 }
1666
1667 rdpe_add (gdpe_Rel (res), gdpe_Rel (g1), gdpe_Rel (g2));
1668 gdpe_update_abs_from_rel (res);
1669 }
1670
1671
1672 /***********************************************************
1673 ** functions for cdpe_t **
1674 ***********************************************************/
1675
1676 /* normalize both parts: mantissa in [1/2, 1) */
1677
1678 #define cdpe_Norm(C) rdpe_Norm (cdpe_Re (C)); rdpe_Norm (cdpe_Im (C));
1679
1680 /* base constants */
1681 const cdpe_t cdpe_zero = { { { { 0.0, 0L } }, { { 0.0, 0L } } } };
1682 const cdpe_t cdpe_one = { { { { 0.5, 1L } }, { { 0.0, 0L } } } };
1683 const cdpe_t cdpe_i = { { { { 0.0, 0L } }, { { 0.5, 1L } } } };
1684
1685 void
cdpe_d(cdpe_t temp_cdpe,double r,double i)1686 cdpe_d (cdpe_t temp_cdpe, double r, double i)
1687 /* return (r, i) as a cdpe_t */
1688 {
1689 rdpe_Mnt (cdpe_Re (temp_cdpe)) = r;
1690 rdpe_Esp (cdpe_Re (temp_cdpe)) = 0L;
1691 rdpe_Mnt (cdpe_Im (temp_cdpe)) = i;
1692 rdpe_Esp (cdpe_Im (temp_cdpe)) = 0L;
1693 cdpe_Norm (temp_cdpe);
1694 }
1695
1696 void
cdpe_x(cdpe_t temp_cdpe,const cplx_t x)1697 cdpe_x (cdpe_t temp_cdpe, const cplx_t x)
1698 /* return x as a cdpe_t */
1699 {
1700 rdpe_Mnt (cdpe_Re (temp_cdpe)) = cplx_Re (x);
1701 rdpe_Esp (cdpe_Re (temp_cdpe)) = 0L;
1702 rdpe_Mnt (cdpe_Im (temp_cdpe)) = cplx_Im (x);
1703 rdpe_Esp (cdpe_Im (temp_cdpe)) = 0L;
1704 cdpe_Norm (temp_cdpe);
1705 }
1706
1707 void
cdpe_e(cdpe_t temp_cdpe,const rdpe_t er,const rdpe_t ei)1708 cdpe_e (cdpe_t temp_cdpe, const rdpe_t er, const rdpe_t ei)
1709 /* return (er, ei) */
1710 {
1711 rdpe_Move (cdpe_Re (temp_cdpe), er);
1712 rdpe_Move (cdpe_Im (temp_cdpe), ei);
1713 }
1714
1715 void
cdpe_2dl(cdpe_t temp_cdpe,double dr,long lr,double di,long li)1716 cdpe_2dl (cdpe_t temp_cdpe, double dr, long lr, double di, long li)
1717 /* return (dr*2^lr, di*2^li) as a cdpe_t */
1718 {
1719 rdpe_Mnt (cdpe_Re (temp_cdpe)) = dr;
1720 rdpe_Esp (cdpe_Re (temp_cdpe)) = lr;
1721 rdpe_Mnt (cdpe_Im (temp_cdpe)) = di;
1722 rdpe_Esp (cdpe_Im (temp_cdpe)) = li;
1723 cdpe_Norm (temp_cdpe);
1724 }
1725
1726 void
cdpe_init(cdpe_t c)1727 cdpe_init (cdpe_t c)
1728 /* c = 0 + I 0 */
1729 {
1730 cdpe_Move (c, cdpe_zero);
1731 }
1732
1733 void
cdpe_set(cdpe_t rc,const cdpe_t c)1734 cdpe_set (cdpe_t rc, const cdpe_t c)
1735 /* rc = c */
1736 {
1737 cdpe_Move (rc, c);
1738 }
1739
1740 void
cdpe_set_x(cdpe_t c,const cplx_t x)1741 cdpe_set_x (cdpe_t c, const cplx_t x)
1742 /* c = (cdpe_t) x */
1743 {
1744 cdpe_Move (c, cdpe_zero);
1745 rdpe_Mnt (cdpe_Re (c)) = cplx_Re (x);
1746 rdpe_Mnt (cdpe_Im (c)) = cplx_Im (x);
1747 cdpe_Norm (c);
1748 }
1749
1750 void
cdpe_set_e(cdpe_t c,const rdpe_t er,const rdpe_t ei)1751 cdpe_set_e (cdpe_t c, const rdpe_t er, const rdpe_t ei)
1752 /* c = er + I ei */
1753 {
1754 rdpe_Move (cdpe_Re (c), er);
1755 rdpe_Move (cdpe_Im (c), ei);
1756 }
1757
1758 void
cdpe_set_d(cdpe_t c,double dr,double di)1759 cdpe_set_d (cdpe_t c, double dr, double di)
1760 /* c = dr + I di */
1761 {
1762 cdpe_set (c, cdpe_zero);
1763 rdpe_Mnt (cdpe_Re (c)) = dr;
1764 rdpe_Mnt (cdpe_Im (c)) = di;
1765 cdpe_Norm (c);
1766 }
1767
1768 void
cdpe_set_dl(cdpe_t c,double dr,long int lr,double di,long int li)1769 cdpe_set_dl (cdpe_t c, double dr, long int lr, double di, long int li)
1770 /* c = dr*10^lr + I di*10^li */
1771 {
1772 rdpe_set_dl (cdpe_Re (c), dr, lr);
1773 rdpe_set_dl (cdpe_Im (c), di, li);
1774 }
1775
1776 void
cdpe_set_2dl(cdpe_t c,double dr,long int lr,double di,long int li)1777 cdpe_set_2dl (cdpe_t c, double dr, long int lr, double di, long int li)
1778 /* c = dr*2^lr + I di*2^li */
1779 {
1780 rdpe_Mnt (cdpe_Re (c)) = dr;
1781 rdpe_Esp (cdpe_Re (c)) = lr;
1782 rdpe_Mnt (cdpe_Im (c)) = di;
1783 rdpe_Esp (cdpe_Im (c)) = li;
1784 cdpe_Norm (c);
1785 }
1786
1787 int
cdpe_set_str(cdpe_t c,const char * s)1788 cdpe_set_str (cdpe_t c, const char *s)
1789 /* set from string as (re , im) */
1790 {
1791 if (sscanf
1792 (s, CDPE_INP_FMT, &rdpe_Mnt (cdpe_Re (c)), &rdpe_Esp (cdpe_Re (c)),
1793 &rdpe_Mnt (cdpe_Im (c)), &rdpe_Esp (cdpe_Im (c))) != 4)
1794 return 0;
1795 rdpe_set_dl (cdpe_Re (c), rdpe_Mnt (cdpe_Re (c)), rdpe_Esp (cdpe_Re (c)));
1796 rdpe_set_dl (cdpe_Im (c), rdpe_Mnt (cdpe_Im (c)), rdpe_Esp (cdpe_Im (c)));
1797 return 1;
1798 }
1799
1800 void
cdpe_get_e(rdpe_t er,rdpe_t ei,const cdpe_t c)1801 cdpe_get_e (rdpe_t er, rdpe_t ei, const cdpe_t c)
1802 /* er = re(c), ei = im(c) */
1803 {
1804 rdpe_Move (er, cdpe_Re (c));
1805 rdpe_Move (ei, cdpe_Im (c));
1806 }
1807
1808 void
cdpe_get_x(cplx_t x,const cdpe_t c)1809 cdpe_get_x (cplx_t x, const cdpe_t c)
1810 /* e = im(c) */
1811 {
1812 cplx_set_d (x,
1813 ldexp (rdpe_Mnt (cdpe_Re (c)), (int)rdpe_Esp (cdpe_Re (c))),
1814 ldexp (rdpe_Mnt (cdpe_Im (c)), (int)rdpe_Esp (cdpe_Im (c))));
1815 }
1816
1817 void
cdpe_get_d(double * dr,double * di,const cdpe_t c)1818 cdpe_get_d (double *dr, double *di, const cdpe_t c)
1819 /* *dr = re(c), *di = im(c) */
1820 {
1821 *dr = ldexp (rdpe_Mnt (cdpe_Re (c)), (int)rdpe_Esp (cdpe_Re (c)));
1822 *di = ldexp (rdpe_Mnt (cdpe_Im (c)), (int)rdpe_Esp (cdpe_Im (c)));
1823 }
1824
1825 char *
cdpe_get_str(char * s,const cdpe_t c)1826 cdpe_get_str (char *s, const cdpe_t c)
1827 /* output to string as (re , im) */
1828 {
1829 double dr, di;
1830 long int lr, li;
1831
1832 if (s == NULL && (s = (char*)mps_malloc (DEF_STR_SIZE)) == NULL)
1833 return NULL;
1834 rdpe_get_dl (&dr, &lr, cdpe_Re (c));
1835 rdpe_get_dl (&di, &li, cdpe_Im (c));
1836 sprintf (s, CDPE_OUT_FMT, dr, lr, di, li);
1837 return s;
1838 }
1839
1840 void
cdpe_neg(cdpe_t rc,const cdpe_t c)1841 cdpe_neg (cdpe_t rc, const cdpe_t c)
1842 /* rc = -c */
1843 {
1844 cdpe_Move (rc, c);
1845 rdpe_Mnt (cdpe_Re (rc)) = -rdpe_Mnt (cdpe_Re (rc));
1846 rdpe_Mnt (cdpe_Im (rc)) = -rdpe_Mnt (cdpe_Im (rc));
1847 }
1848
1849 void
cdpe_con(cdpe_t rc,const cdpe_t c)1850 cdpe_con (cdpe_t rc, const cdpe_t c)
1851 /* rc = conj(c) */
1852 {
1853 cdpe_Move (rc, c);
1854 rdpe_Mnt (cdpe_Im (rc)) = -rdpe_Mnt (cdpe_Im (rc));
1855 }
1856
1857 void
cdpe_smod(rdpe_t e,const cdpe_t c)1858 cdpe_smod (rdpe_t e, const cdpe_t c)
1859 /* e = |c|^2 */
1860 {
1861 rdpe_t t;
1862
1863 rdpe_sqr (e, cdpe_Re (c));
1864 rdpe_sqr (t, cdpe_Im (c));
1865 rdpe_add_eq (e, t);
1866 }
1867
1868 void
cdpe_mod(rdpe_t e,const cdpe_t c)1869 cdpe_mod (rdpe_t e, const cdpe_t c)
1870 /* e = |c| */
1871 {
1872 rdpe_t t;
1873
1874 rdpe_sqr (e, cdpe_Re (c));
1875 rdpe_sqr (t, cdpe_Im (c));
1876 rdpe_add_eq (e, t);
1877 rdpe_sqrt_eq (e);
1878 }
1879
1880 void
cdpe_inv(cdpe_t rc,const cdpe_t c)1881 cdpe_inv (cdpe_t rc, const cdpe_t c)
1882 /* rc = 1 / c */
1883 {
1884 rdpe_t e;
1885
1886 cdpe_smod (e, c);
1887 rdpe_inv_eq (e);
1888 cdpe_Move (rc, c);
1889 rdpe_Mnt (cdpe_Im (rc)) = -rdpe_Mnt (cdpe_Im (rc));
1890 rdpe_mul_eq (cdpe_Re (rc), e);
1891 rdpe_mul_eq (cdpe_Im (rc), e);
1892 }
1893
1894 void
cdpe_sqr(cdpe_t rc,const cdpe_t c)1895 cdpe_sqr (cdpe_t rc, const cdpe_t c)
1896 /* rc = c * c */
1897 {
1898 rdpe_t e1, e2;
1899
1900 rdpe_mul (e1, cdpe_Re (c), cdpe_Re (c));
1901 rdpe_mul (e2, cdpe_Im (c), cdpe_Im (c));
1902 rdpe_mul (cdpe_Im (rc), cdpe_Im (c), cdpe_Re (c));
1903 rdpe_Esp (cdpe_Im (rc)) += 1; /* multiply by 2 */
1904 rdpe_sub (cdpe_Re (rc), e1, e2);
1905 }
1906
1907 void
cdpe_rot(cdpe_t rc,const cdpe_t c)1908 cdpe_rot (cdpe_t rc, const cdpe_t c)
1909 /* rc = I c */
1910 {
1911 rdpe_t e;
1912
1913 rdpe_Move (e, cdpe_Re (c));
1914 rdpe_Move (cdpe_Re (rc), cdpe_Im (c));
1915 rdpe_Move (cdpe_Im (rc), e);
1916 rdpe_Mnt (cdpe_Re (rc)) = -rdpe_Mnt (cdpe_Re (rc));
1917 }
1918
1919 void
cdpe_flip(cdpe_t rc,const cdpe_t c)1920 cdpe_flip (cdpe_t rc, const cdpe_t c)
1921 /* rc = (Im(c), Re(c)) */
1922 {
1923 rdpe_t e;
1924
1925 rdpe_Move (e, cdpe_Re (c));
1926 rdpe_Move (cdpe_Re (rc), cdpe_Im (c));
1927 rdpe_Move (cdpe_Im (rc), e);
1928 }
1929
1930 void
cdpe_add(cdpe_t rc,const cdpe_t c1,const cdpe_t c2)1931 cdpe_add (cdpe_t rc, const cdpe_t c1, const cdpe_t c2)
1932 /* rc = c1 + c2 */
1933 {
1934 rdpe_add (cdpe_Re (rc), cdpe_Re (c1), cdpe_Re (c2));
1935 rdpe_add (cdpe_Im (rc), cdpe_Im (c1), cdpe_Im (c2));
1936 }
1937
1938 void
cdpe_sub(cdpe_t rc,const cdpe_t c1,const cdpe_t c2)1939 cdpe_sub (cdpe_t rc, const cdpe_t c1, const cdpe_t c2)
1940 /* rc = c1 - c2 */
1941 {
1942 rdpe_sub (cdpe_Re (rc), cdpe_Re (c1), cdpe_Re (c2));
1943 rdpe_sub (cdpe_Im (rc), cdpe_Im (c1), cdpe_Im (c2));
1944 }
1945
1946 void
cdpe_mul(cdpe_t rc,const cdpe_t c1,const cdpe_t c2)1947 cdpe_mul (cdpe_t rc, const cdpe_t c1, const cdpe_t c2)
1948 /* rc = c1 * c2 */
1949 {
1950 rdpe_t e1, e2, e3;
1951
1952 rdpe_mul (e1, cdpe_Re (c1), cdpe_Re (c2));
1953 rdpe_mul (e2, cdpe_Im (c1), cdpe_Im (c2));
1954 rdpe_sub (e3, e1, e2); /* needed when rc=c1 or rc=c2 */
1955 rdpe_mul (e1, cdpe_Im (c1), cdpe_Re (c2));
1956 rdpe_mul (e2, cdpe_Re (c1), cdpe_Im (c2));
1957 rdpe_Move (cdpe_Re (rc), e3);
1958 rdpe_add (cdpe_Im (rc), e1, e2);
1959 }
1960
1961 void
cdpe_mul_e(cdpe_t rc,const cdpe_t c,const rdpe_t e)1962 cdpe_mul_e (cdpe_t rc, const cdpe_t c, const rdpe_t e)
1963 /* rc = c * e */
1964 {
1965 rdpe_Mnt (cdpe_Re (rc)) = rdpe_Mnt (cdpe_Re (c)) * rdpe_Mnt (e);
1966 rdpe_Esp (cdpe_Re (rc)) = rdpe_Esp (cdpe_Re (c)) + rdpe_Esp (e);
1967 rdpe_Mnt (cdpe_Im (rc)) = rdpe_Mnt (cdpe_Im (c)) * rdpe_Mnt (e);
1968 rdpe_Esp (cdpe_Im (rc)) = rdpe_Esp (cdpe_Im (c)) + rdpe_Esp (e);
1969 cdpe_Norm (rc);
1970 }
1971
1972 void
cdpe_mul_x(cdpe_t rc,const cdpe_t c,const cplx_t x)1973 cdpe_mul_x (cdpe_t rc, const cdpe_t c, const cplx_t x)
1974 /* rc = c * x */
1975 {
1976 rdpe_t e1, e2, e3;
1977
1978 rdpe_mul_d (e1, cdpe_Re (c), cplx_Re (x));
1979 rdpe_mul_d (e2, cdpe_Im (c), cplx_Im (x));
1980 rdpe_sub (e3, e1, e2); /* needed when rc=c1 or rc=c2 */
1981 rdpe_mul_d (e1, cdpe_Im (c), cplx_Re (x));
1982 rdpe_mul_d (e2, cdpe_Re (c), cplx_Im (x));
1983 rdpe_Move (cdpe_Re (rc), e3);
1984 rdpe_add (cdpe_Im (rc), e1, e2);
1985 }
1986
1987 void
cdpe_mul_d(cdpe_t rc,const cdpe_t c,double d)1988 cdpe_mul_d (cdpe_t rc, const cdpe_t c, double d)
1989 /* rc = c * d */
1990 {
1991 cdpe_Move (rc, c);
1992 rdpe_Mnt (cdpe_Re (rc)) *= d;
1993 rdpe_Mnt (cdpe_Im (rc)) *= d;
1994 cdpe_Norm (rc);
1995 }
1996
1997 void
cdpe_mul_2exp(cdpe_t rc,const cdpe_t c,unsigned long int i)1998 cdpe_mul_2exp (cdpe_t rc, const cdpe_t c, unsigned long int i)
1999 /* rc = c * 2^i */
2000 {
2001 cdpe_Move (rc, c);
2002 rdpe_Esp (cdpe_Re (rc)) += i;
2003 rdpe_Esp (cdpe_Im (rc)) += i;
2004 }
2005
2006 void
cdpe_div(cdpe_t rc,const cdpe_t c1,const cdpe_t c2)2007 cdpe_div (cdpe_t rc, const cdpe_t c1, const cdpe_t c2)
2008 /* rc = c1 / c2 */
2009 {
2010 cdpe_t t; /* needed when rc=c1 or rc=c2 */
2011 rdpe_t e1, e2, e3;
2012
2013 cdpe_smod (e1, c2);
2014 cdpe_div_e (t, c2, e1);
2015 rdpe_Mnt (cdpe_Im (t)) = -rdpe_Mnt (cdpe_Im (t));
2016 rdpe_mul (e1, cdpe_Re (c1), cdpe_Re (t));
2017 rdpe_mul (e2, cdpe_Im (c1), cdpe_Im (t));
2018 rdpe_sub (e3, e1, e2);
2019 rdpe_mul (e1, cdpe_Im (c1), cdpe_Re (t));
2020 rdpe_mul (e2, cdpe_Re (c1), cdpe_Im (t));
2021 rdpe_Move (cdpe_Re (rc), e3);
2022 rdpe_add (cdpe_Im (rc), e1, e2);
2023 }
2024
2025 void
cdpe_div_e(cdpe_t rc,const cdpe_t c,const rdpe_t e)2026 cdpe_div_e (cdpe_t rc, const cdpe_t c, const rdpe_t e)
2027 /* rc = c / e */
2028 {
2029 rdpe_Mnt (cdpe_Re (rc)) = rdpe_Mnt (cdpe_Re (c)) / rdpe_Mnt (e);
2030 rdpe_Esp (cdpe_Re (rc)) = rdpe_Esp (cdpe_Re (c)) - rdpe_Esp (e);
2031 rdpe_Mnt (cdpe_Im (rc)) = rdpe_Mnt (cdpe_Im (c)) / rdpe_Mnt (e);
2032 rdpe_Esp (cdpe_Im (rc)) = rdpe_Esp (cdpe_Im (c)) - rdpe_Esp (e);
2033 cdpe_Norm (rc);
2034 }
2035
2036 void
cdpe_div_d(cdpe_t rc,const cdpe_t c,double d)2037 cdpe_div_d (cdpe_t rc, const cdpe_t c, double d)
2038 /* rc = c / d */
2039 {
2040 cdpe_Move (rc, c);
2041 rdpe_Mnt (cdpe_Re (rc)) /= d;
2042 rdpe_Mnt (cdpe_Im (rc)) /= d;
2043 cdpe_Norm (rc);
2044 }
2045
2046 void
cdpe_div_2exp(cdpe_t rc,const cdpe_t c,unsigned long int i)2047 cdpe_div_2exp (cdpe_t rc, const cdpe_t c, unsigned long int i)
2048 /* rc = c / 2^i */
2049 {
2050 cdpe_Move (rc, c);
2051 rdpe_Esp (cdpe_Re (rc)) -= i;
2052 rdpe_Esp (cdpe_Im (rc)) -= i;
2053 }
2054
2055 void
cdpe_pow_si(cdpe_t rc,const cdpe_t c,register signed long int i)2056 cdpe_pow_si (cdpe_t rc, const cdpe_t c, register signed long int i)
2057 /* rc = c^i, i integer */
2058 {
2059 cdpe_t t;
2060
2061 cdpe_Move (t, c);
2062 cdpe_Move (rc, cdpe_one);
2063
2064 if (i < 0)
2065 {
2066 cdpe_inv (t, t);
2067 i = -i;
2068 }
2069 while (i)
2070 {
2071 if (i & 1)
2072 cdpe_mul_eq (rc, t);
2073 cdpe_sqr_eq (t);
2074 i >>= 1; /* divide i by 2 */
2075 }
2076 }
2077
2078 void
cdpe_swap(cdpe_t c1,cdpe_t c2)2079 cdpe_swap (cdpe_t c1, cdpe_t c2)
2080 /* c1 <-> c2 */
2081 {
2082 cdpe_t t;
2083
2084 cdpe_Move (t, c1);
2085 cdpe_Move (c1, c2);
2086 cdpe_Move (c2, t);
2087 }
2088
2089 void
cdpe_neg_eq(cdpe_t c)2090 cdpe_neg_eq (cdpe_t c)
2091 /* c = -c */
2092 {
2093 rdpe_Mnt (cdpe_Re (c)) = -rdpe_Mnt (cdpe_Re (c));
2094 rdpe_Mnt (cdpe_Im (c)) = -rdpe_Mnt (cdpe_Im (c));
2095 }
2096
2097 void
cdpe_con_eq(cdpe_t c)2098 cdpe_con_eq (cdpe_t c)
2099 /* c = conj(c) */
2100 {
2101 rdpe_Mnt (cdpe_Im (c)) = -rdpe_Mnt (cdpe_Im (c));
2102 }
2103
2104 void
cdpe_inv_eq(cdpe_t c)2105 cdpe_inv_eq (cdpe_t c)
2106 /* c = 1 / c */
2107 {
2108 rdpe_t e;
2109
2110 cdpe_smod (e, c);
2111 rdpe_inv_eq (e);
2112 rdpe_Mnt (cdpe_Im (c)) = -rdpe_Mnt (cdpe_Im (c));
2113 rdpe_mul_eq (cdpe_Re (c), e);
2114 rdpe_mul_eq (cdpe_Im (c), e);
2115 }
2116
2117 void
cdpe_sqr_eq(cdpe_t c)2118 cdpe_sqr_eq (cdpe_t c)
2119 /* c = c * c */
2120 {
2121 rdpe_t e1, e2;
2122
2123 rdpe_sqr (e1, cdpe_Re (c));
2124 rdpe_sqr (e2, cdpe_Im (c));
2125 rdpe_mul_eq (cdpe_Im (c), cdpe_Re (c));
2126 rdpe_Esp (cdpe_Im (c)) += 1; /* multiply by 2 */
2127 rdpe_sub (cdpe_Re (c), e1, e2);
2128 }
2129
2130 void
cdpe_rot_eq(cdpe_t c)2131 cdpe_rot_eq (cdpe_t c)
2132 /* c = I c */
2133 {
2134 rdpe_t e;
2135
2136 rdpe_Move (e, cdpe_Re (c));
2137 rdpe_Move (cdpe_Re (c), cdpe_Im (c));
2138 rdpe_Move (cdpe_Im (c), e);
2139 rdpe_Mnt (cdpe_Re (c)) = -rdpe_Mnt (cdpe_Re (c));
2140 }
2141
2142 void
cdpe_flip_eq(cdpe_t c)2143 cdpe_flip_eq (cdpe_t c)
2144 /* c = (Im(c), Re(c)) */
2145 {
2146 rdpe_t e;
2147
2148 rdpe_Move (e, cdpe_Re (c));
2149 rdpe_Move (cdpe_Re (c), cdpe_Im (c));
2150 rdpe_Move (cdpe_Im (c), e);
2151 }
2152
2153 void
cdpe_add_eq(cdpe_t rc,const cdpe_t c)2154 cdpe_add_eq (cdpe_t rc, const cdpe_t c)
2155 /* rc = rc + c2 */
2156 {
2157 rdpe_add_eq (cdpe_Re (rc), cdpe_Re (c));
2158 rdpe_add_eq (cdpe_Im (rc), cdpe_Im (c));
2159 }
2160
2161 void
cdpe_sub_eq(cdpe_t rc,const cdpe_t c)2162 cdpe_sub_eq (cdpe_t rc, const cdpe_t c)
2163 /* rc = rc - c2 */
2164 {
2165 rdpe_sub_eq (cdpe_Re (rc), cdpe_Re (c));
2166 rdpe_sub_eq (cdpe_Im (rc), cdpe_Im (c));
2167 }
2168
2169 void
cdpe_mul_eq(cdpe_t rc,const cdpe_t c)2170 cdpe_mul_eq (cdpe_t rc, const cdpe_t c)
2171 /* rc = rc * c */
2172 {
2173 rdpe_t e1, e2, e3;
2174
2175 rdpe_mul (e1, cdpe_Re (rc), cdpe_Re (c));
2176 rdpe_mul (e2, cdpe_Im (rc), cdpe_Im (c));
2177 rdpe_sub (e3, e1, e2);
2178 rdpe_mul (e1, cdpe_Im (rc), cdpe_Re (c));
2179 rdpe_mul (e2, cdpe_Re (rc), cdpe_Im (c));
2180 rdpe_Move (cdpe_Re (rc), e3);
2181 rdpe_add (cdpe_Im (rc), e1, e2);
2182 }
2183
2184 void
cdpe_mul_eq_e(cdpe_t c,const rdpe_t e)2185 cdpe_mul_eq_e (cdpe_t c, const rdpe_t e)
2186 /* c = c * e */
2187 {
2188 rdpe_Mnt (cdpe_Re (c)) *= rdpe_Mnt (e);
2189 rdpe_Esp (cdpe_Re (c)) += rdpe_Esp (e);
2190 rdpe_Mnt (cdpe_Im (c)) *= rdpe_Mnt (e);
2191 rdpe_Esp (cdpe_Im (c)) += rdpe_Esp (e);
2192 cdpe_Norm (c);
2193 }
2194
2195 void
cdpe_mul_eq_x(cdpe_t c,const cplx_t x)2196 cdpe_mul_eq_x (cdpe_t c, const cplx_t x)
2197 /* c *= x */
2198 {
2199 rdpe_t e1, e2, e3;
2200
2201 rdpe_mul_d (e1, cdpe_Re (c), cplx_Re (x));
2202 rdpe_mul_d (e2, cdpe_Im (c), cplx_Im (x));
2203 rdpe_sub (e3, e1, e2); /* needed when rc=c1 or rc=c2 */
2204 rdpe_mul_d (e1, cdpe_Im (c), cplx_Re (x));
2205 rdpe_mul_d (e2, cdpe_Re (c), cplx_Im (x));
2206 rdpe_Move (cdpe_Re (c), e3);
2207 rdpe_add (cdpe_Im (c), e1, e2);
2208 }
2209
2210 void
cdpe_mul_eq_d(cdpe_t c,double d)2211 cdpe_mul_eq_d (cdpe_t c, double d)
2212 /* c = c * d */
2213 {
2214 rdpe_Mnt (cdpe_Re (c)) *= d;
2215 rdpe_Mnt (cdpe_Im (c)) *= d;
2216 cdpe_Norm (c);
2217 }
2218
2219 void
cdpe_mul_eq_2exp(cdpe_t c,unsigned long int i)2220 cdpe_mul_eq_2exp (cdpe_t c, unsigned long int i)
2221 /* c = c * 2^i */
2222 {
2223 rdpe_Esp (cdpe_Re (c)) += i;
2224 rdpe_Esp (cdpe_Im (c)) += i;
2225 }
2226
2227 void
cdpe_div_eq(cdpe_t rc,const cdpe_t c)2228 cdpe_div_eq (cdpe_t rc, const cdpe_t c)
2229 /* rc = rc / c */
2230 {
2231 cdpe_t t;
2232 rdpe_t e1, e2, e3;
2233
2234 cdpe_smod (e1, c);
2235 cdpe_div_e (t, c, e1);
2236 rdpe_Mnt (cdpe_Im (t)) = -rdpe_Mnt (cdpe_Im (t));
2237 rdpe_mul (e1, cdpe_Re (c), cdpe_Re (t));
2238 rdpe_mul (e2, cdpe_Im (c), cdpe_Im (t));
2239 rdpe_sub (e3, e1, e2);
2240 rdpe_mul (e1, cdpe_Im (c), cdpe_Re (t));
2241 rdpe_mul (e2, cdpe_Re (c), cdpe_Im (t));
2242 rdpe_Move (cdpe_Re (rc), e3);
2243 rdpe_add (cdpe_Im (rc), e1, e2);
2244 }
2245
2246 void
cdpe_div_eq_e(cdpe_t c,const rdpe_t e)2247 cdpe_div_eq_e (cdpe_t c, const rdpe_t e)
2248 /* c = c / e */
2249 {
2250 rdpe_Mnt (cdpe_Re (c)) /= rdpe_Mnt (e);
2251 rdpe_Esp (cdpe_Re (c)) -= rdpe_Esp (e);
2252 rdpe_Mnt (cdpe_Im (c)) /= rdpe_Mnt (e);
2253 rdpe_Esp (cdpe_Im (c)) -= rdpe_Esp (e);
2254 cdpe_Norm (c);
2255 }
2256
2257 void
cdpe_div_eq_d(cdpe_t c,double d)2258 cdpe_div_eq_d (cdpe_t c, double d)
2259 /* c = c / d */
2260 {
2261 rdpe_Mnt (cdpe_Re (c)) /= d;
2262 rdpe_Mnt (cdpe_Im (c)) /= d;
2263 cdpe_Norm (c);
2264 }
2265
2266 void
cdpe_div_eq_2exp(cdpe_t c,unsigned long int i)2267 cdpe_div_eq_2exp (cdpe_t c, unsigned long int i)
2268 /* c = c / 2^i */
2269 {
2270 rdpe_Esp (cdpe_Re (c)) -= i;
2271 rdpe_Esp (cdpe_Im (c)) -= i;
2272 }
2273
2274 void
cdpe_pow_eq_si(cdpe_t c,register signed long int i)2275 cdpe_pow_eq_si (cdpe_t c, register signed long int i)
2276 /* rc = c^i, i integer */
2277 {
2278 cdpe_t t;
2279
2280 cdpe_Move (t, c);
2281 cdpe_Move (c, cdpe_one);
2282
2283 if (i < 0)
2284 {
2285 cdpe_inv (t, t);
2286 i = -i;
2287 }
2288 while (i)
2289 {
2290 if (i & 1)
2291 cdpe_mul_eq (c, t);
2292 cdpe_sqr_eq (t);
2293 i >>= 1; /* divide i by 2 */
2294 }
2295 }
2296
2297 /*------------ relational ops. -------------------------*/
2298
2299 int
cdpe_eq_zero(const cdpe_t c)2300 cdpe_eq_zero (const cdpe_t c)
2301 /* c == 0 */
2302 {
2303 return rdpe_Mnt (cdpe_Re (c)) == 0.0 && rdpe_Esp (cdpe_Re (c)) == 0 &&
2304 rdpe_Mnt (cdpe_Im (c)) == 0.0 && rdpe_Esp (cdpe_Im (c)) == 0;
2305 }
2306
2307 int
cdpe_eq(const cdpe_t c1,const cdpe_t c2)2308 cdpe_eq (const cdpe_t c1, const cdpe_t c2)
2309 /* c1 == c2 */
2310 {
2311 return rdpe_Mnt (cdpe_Re (c1)) == rdpe_Mnt (cdpe_Re (c2)) &&
2312 rdpe_Esp (cdpe_Re (c1)) == rdpe_Esp (cdpe_Re (c2)) &&
2313 rdpe_Mnt (cdpe_Im (c1)) == rdpe_Mnt (cdpe_Im (c2)) &&
2314 rdpe_Esp (cdpe_Im (c1)) == rdpe_Esp (cdpe_Im (c2));
2315 }
2316
2317 int
cdpe_ne(const cdpe_t c1,const cdpe_t c2)2318 cdpe_ne (const cdpe_t c1, const cdpe_t c2)
2319 /* c1 != c2 */
2320 {
2321 return rdpe_Mnt (cdpe_Re (c1)) != rdpe_Mnt (cdpe_Re (c2)) ||
2322 rdpe_Esp (cdpe_Re (c1)) != rdpe_Esp (cdpe_Re (c2)) ||
2323 rdpe_Mnt (cdpe_Im (c1)) != rdpe_Mnt (cdpe_Im (c2)) ||
2324 rdpe_Esp (cdpe_Im (c1)) != rdpe_Esp (cdpe_Im (c2));
2325 }
2326
2327 /*------------ I/O functions ---------------------------*/
2328
2329 int
cdpe_out_str_u(FILE * f,const cdpe_t c)2330 cdpe_out_str_u (FILE * f, const cdpe_t c)
2331 /* output as mant e exp mant e exp */
2332 {
2333 if (f == NULL)
2334 f = stdout;
2335 if (rdpe_out_str_u (f, cdpe_Re (c)) < 0)
2336 return -1;
2337 if (fprintf (f, " ") < 0)
2338 return -1;
2339 if (rdpe_out_str_u (f, cdpe_Im (c)) < 0)
2340 return -1;
2341 return 0;
2342 }
2343
2344 int
cdpe_out_str(FILE * f,const cdpe_t c)2345 cdpe_out_str (FILE * f, const cdpe_t c)
2346 /* output as (mant x exp , mant x exp) */
2347 {
2348 if (f == NULL)
2349 f = stdout;
2350 if (fputc ('(', f) == EOF)
2351 return -1;
2352 if (rdpe_out_str (f, cdpe_Re (c)) < 0)
2353 return -1;
2354 if (fprintf (f, ", ") < 0)
2355 return -1;
2356 if (rdpe_out_str (f, cdpe_Im (c)) < 0)
2357 return -1;
2358 return fputc (')', f);
2359 }
2360
2361 int
cdpe_inp_str_u(cdpe_t c,FILE * f)2362 cdpe_inp_str_u (cdpe_t c, FILE * f)
2363 /* input from file as mant e exp mant e exp */
2364 {
2365 double dr, di;
2366 long int lr, li;
2367
2368 if (f == NULL)
2369 f = stdin;
2370 if (fscanf (f, CDPE_INP_UFMT, &dr, &lr, &di, &li) != 4)
2371 return 0;
2372 rdpe_set_dl (cdpe_Re (c), dr, lr);
2373 rdpe_set_dl (cdpe_Im (c), di, li);
2374 return 1;
2375 }
2376
2377 int
cdpe_inp_str(cdpe_t c,FILE * f)2378 cdpe_inp_str (cdpe_t c, FILE * f)
2379 /* input from file as (mant x exp , mant x exp) */
2380 {
2381 double dr, di;
2382 long int lr, li;
2383
2384 if (f == NULL)
2385 f = stdin;
2386 if (fscanf (f, CDPE_INP_FMT, &dr, &lr, &di, &li) != 4)
2387 return 0;
2388 rdpe_set_dl (cdpe_Re (c), dr, lr);
2389 rdpe_set_dl (cdpe_Im (c), di, li);
2390 return 1;
2391 }
2392
2393 /*------------ vector functions ------------------------*/
2394
2395 void
cdpe_vinit(cdpe_t v[],long size)2396 cdpe_vinit (cdpe_t v[], long size)
2397 {
2398 long i;
2399
2400 for (i = 0; i < size; i++)
2401 cdpe_Move (v[i], cdpe_zero);
2402 }
2403
2404 /***********************************************************
2405 ** **
2406 ***********************************************************/
2407