changeset 4388 | 742f099741bf |
parent 4387 | 879309cae427 |
child 4389 | 54ec85aa8943 |
4387:879309cae427 | 4388:742f099741bf |
---|---|
1 " |
1 " |
2 COPYRIGHT (c) 2017 by eXept Software AG |
2 COPYRIGHT (c) 2017 by eXept Software AG |
3 All Rights Reserved |
3 All Rights Reserved |
4 |
4 |
5 This software is furnished under a license and may be used |
5 This software is furnished under a license and may be used |
6 only in accordance with the terms of that license and with the |
6 only in accordance with the terms of that license and with the |
7 inclusion of the above copyright notice. This software may not |
7 inclusion of the above copyright notice. This software may not |
8 be provided or otherwise made available to, or used by, any |
8 be provided or otherwise made available to, or used by, any |
63 |
63 |
64 # ifndef _FPU_DOUBLE |
64 # ifndef _FPU_DOUBLE |
65 # define _FPU_DOUBLE 0x0200 |
65 # define _FPU_DOUBLE 0x0200 |
66 # endif |
66 # endif |
67 |
67 |
68 # if defined( __win32__ ) && (defined( __BORLANDC__ ) || defined( __VISUALC__ )) |
68 # if defined( __win32__ ) && (defined( __BORLANDC__ ) || defined( __VISUALC__ )) |
69 |
69 |
70 # define fpu_fix_start(old_cw_ptr)\ |
70 # define fpu_fix_start(old_cw_ptr)\ |
71 {\ |
71 {\ |
72 *old_cw_ptr = _control87(0, 0); \ |
72 *old_cw_ptr = _control87(0, 0); \ |
73 _control87(_FPU_DOUBLE, _FPU_EXTENDED);\ |
73 _control87(_FPU_DOUBLE, _FPU_EXTENDED);\ |
74 } |
74 } |
75 |
75 |
76 # define fpu_fix_end(old_cw_ptr)\ |
76 # define fpu_fix_end(old_cw_ptr)\ |
77 {\ |
77 {\ |
78 _control87(*old_cw_ptr, _FPU_EXTENDED);\ |
78 _control87(*old_cw_ptr, _FPU_EXTENDED);\ |
79 } |
79 } |
80 |
80 |
81 # else // assume MINGW, GCC or CLANG |
81 # else // assume MINGW, GCC or CLANG |
82 |
82 |
83 # ifndef _FPU_GETCW |
83 # ifndef _FPU_GETCW |
87 # define _FPU_SETCW(x) asm volatile ("fldcw %0": :"m" (x)); |
87 # define _FPU_SETCW(x) asm volatile ("fldcw %0": :"m" (x)); |
88 # endif |
88 # endif |
89 |
89 |
90 # define fpu_fix_start(old_cw_ptr)\ |
90 # define fpu_fix_start(old_cw_ptr)\ |
91 {\ |
91 {\ |
92 volatile unsigned short cw, new_cw;\ |
92 volatile unsigned short cw, new_cw;\ |
93 _FPU_GETCW(cw);\ |
93 _FPU_GETCW(cw);\ |
94 new_cw = (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;\ |
94 new_cw = (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;\ |
95 _FPU_SETCW(new_cw);\ |
95 _FPU_SETCW(new_cw);\ |
96 *old_cw_ptr = cw;\ |
96 *old_cw_ptr = cw;\ |
97 } |
97 } |
98 |
98 |
99 # define fpu_fix_end(old_cw_ptr)\ |
99 # define fpu_fix_end(old_cw_ptr)\ |
100 {\ |
100 {\ |
101 volatile unsigned short cw = *old_cw_ptr;\ |
101 volatile unsigned short cw = *old_cw_ptr;\ |
102 _FPU_SETCW(cw);\ |
102 _FPU_SETCW(cw);\ |
103 } |
103 } |
104 |
104 |
105 # endif |
105 # endif |
106 |
106 |
107 #endif |
107 #endif |
110 struct qd_real { |
110 struct qd_real { |
111 double x[4]; /* The Components. */ |
111 double x[4]; /* The Components. */ |
112 }; |
112 }; |
113 |
113 |
114 struct __quadDoubleStruct { |
114 struct __quadDoubleStruct { |
115 STX_OBJ_HEADER |
115 STX_OBJ_HEADER |
116 #ifdef __NEED_DOUBLE_ALIGN |
116 #ifdef __NEED_DOUBLE_ALIGN |
117 __FILLTYPE_DOUBLE f_filler; |
117 __FILLTYPE_DOUBLE f_filler; |
118 #endif |
118 #endif |
119 double d_quadDoubleValue[4]; |
119 double d_quadDoubleValue[4]; |
120 }; |
120 }; |
121 |
121 |
122 #define __QuadDoubleInstPtr(obj) ((struct __quadDoubleStruct *)(__objPtr(obj))) |
122 #define __QuadDoubleInstPtr(obj) ((struct __quadDoubleStruct *)(__objPtr(obj))) |
123 |
123 |
124 #ifndef __isQuadDouble |
124 #ifndef __isQuadDouble |
125 # define __isQuadDouble(o) \ |
125 # define __isQuadDouble(o) \ |
126 (__Class(o) == @global(QuadDouble)) |
126 (__Class(o) == @global(QuadDouble)) |
127 #endif |
127 #endif |
128 |
128 |
129 #ifndef __qIsQuadDouble |
129 #ifndef __qIsQuadDouble |
130 # define __qIsQuadDouble(o) \ |
130 # define __qIsQuadDouble(o) \ |
131 (__qClass(o) == @global(QuadDouble)) |
131 (__qClass(o) == @global(QuadDouble)) |
132 #endif |
132 #endif |
133 |
133 |
134 #define __qNew_qdReal(newQD, d0,d1,d2,d3) { \ |
134 #define __qNew_qdReal(newQD, d0,d1,d2,d3) { \ |
135 __qNew(newQD, sizeof(struct __quadDoubleStruct)); \ |
135 __qNew(newQD, sizeof(struct __quadDoubleStruct)); \ |
136 __stx_setClass(newQD, QDouble); \ |
136 __stx_setClass(newQD, QDouble); \ |
254 #define m_renorm4(c0, c1, c2, c3) {\ |
254 #define m_renorm4(c0, c1, c2, c3) {\ |
255 double s0, s1, s2 = 0.0, s3 = 0.0;\ |
255 double s0, s1, s2 = 0.0, s3 = 0.0;\ |
256 \ |
256 \ |
257 if (! isinf(c0)) { \ |
257 if (! isinf(c0)) { \ |
258 \ |
258 \ |
259 m_quick_two_sum(s0, c2, c3, c3);\ |
259 m_quick_two_sum(s0, c2, c3, c3);\ |
260 m_quick_two_sum(s0, c1, s0, c2);\ |
260 m_quick_two_sum(s0, c1, s0, c2);\ |
261 m_quick_two_sum(c0, c0, s0, c1);\ |
261 m_quick_two_sum(c0, c0, s0, c1);\ |
262 \ |
262 \ |
263 s0 = c0;\ |
263 s0 = c0;\ |
264 s1 = c1;\ |
264 s1 = c1;\ |
265 if (s1 != 0.0) {\ |
265 if (s1 != 0.0) {\ |
266 m_quick_two_sum(s1, s1, c2, s2);\ |
266 m_quick_two_sum(s1, s1, c2, s2);\ |
267 if (s2 != 0.0) {\ |
267 if (s2 != 0.0) {\ |
268 m_quick_two_sum(s2, s2, c3, s3);\ |
268 m_quick_two_sum(s2, s2, c3, s3);\ |
269 } else {\ |
269 } else {\ |
270 m_quick_two_sum(s1, s1, c3, s2);\ |
270 m_quick_two_sum(s1, s1, c3, s2);\ |
271 }\ |
271 }\ |
272 } else {\ |
272 } else {\ |
273 m_quick_two_sum(s0, s0, c2, s1);\ |
273 m_quick_two_sum(s0, s0, c2, s1);\ |
274 if (s1 != 0.0) {\ |
274 if (s1 != 0.0) {\ |
275 m_quick_two_sum(s1, s1, c3, s2);\ |
275 m_quick_two_sum(s1, s1, c3, s2);\ |
276 } else {\ |
276 } else {\ |
277 m_quick_two_sum(s0, s0, c3, s1);\ |
277 m_quick_two_sum(s0, s0, c3, s1);\ |
278 }\ |
278 }\ |
279 }\ |
279 }\ |
280 \ |
280 \ |
281 c0 = s0;\ |
281 c0 = s0;\ |
282 c1 = s1;\ |
282 c1 = s1;\ |
283 c2 = s2;\ |
283 c2 = s2;\ |
284 c3 = s3;\ |
284 c3 = s3;\ |
285 }\ |
285 }\ |
286 } |
286 } |
287 |
287 |
288 #define m_renorm5(c0, c1, c2, c3, c4) { \ |
288 #define m_renorm5(c0, c1, c2, c3, c4) { \ |
289 double s0, s1, s2 = 0.0, s3 = 0.0; \ |
289 double s0, s1, s2 = 0.0, s3 = 0.0; \ |
290 \ |
290 \ |
291 if (! isinf(c0)) { \ |
291 if (! isinf(c0)) { \ |
292 m_two_sum(s0, c3, c4, c4); \ |
292 m_two_sum(s0, c3, c4, c4); \ |
293 m_quick_two_sum(s0, c2, s0, c3); \ |
293 m_quick_two_sum(s0, c2, s0, c3); \ |
294 m_quick_two_sum(s0, c1, s0, c2); \ |
294 m_quick_two_sum(s0, c1, s0, c2); \ |
295 m_quick_two_sum(c0, c0, s0, c1); \ |
295 m_quick_two_sum(c0, c0, s0, c1); \ |
296 \ |
296 \ |
297 s0 = c0; \ |
297 s0 = c0; \ |
298 s1 = c1; \ |
298 s1 = c1; \ |
299 \ |
299 \ |
300 m_two_sum(s0, c0, c1, s1); \ |
300 m_two_sum(s0, c0, c1, s1); \ |
301 if (s1 != 0.0) { \ |
301 if (s1 != 0.0) { \ |
302 m_quick_two_sum(s1, s1, c2, s2); \ |
302 m_quick_two_sum(s1, s1, c2, s2); \ |
303 if (s2 != 0.0) { \ |
303 if (s2 != 0.0) { \ |
304 m_quick_two_sum(s2 ,s2, c3, s3); \ |
304 m_quick_two_sum(s2 ,s2, c3, s3); \ |
305 if (s3 != 0.0) {\ |
305 if (s3 != 0.0) {\ |
306 s3 += c4; \ |
306 s3 += c4; \ |
307 } else {\ |
307 } else {\ |
308 s2 += c4;\ |
308 s2 += c4;\ |
309 }\ |
309 }\ |
310 } else { \ |
310 } else { \ |
311 m_quick_two_sum(s1, s1, c3, s2); \ |
311 m_quick_two_sum(s1, s1, c3, s2); \ |
312 if (s2 != 0.0) {\ |
312 if (s2 != 0.0) {\ |
313 m_quick_two_sum(s2, s2, c4, s3); \ |
313 m_quick_two_sum(s2, s2, c4, s3); \ |
314 } else { \ |
314 } else { \ |
315 m_quick_two_sum(s1, s1, c4, s2); \ |
315 m_quick_two_sum(s1, s1, c4, s2); \ |
316 } \ |
316 } \ |
317 } \ |
317 } \ |
318 } else { \ |
318 } else { \ |
319 m_quick_two_sum(s0,s0, c2, s1); \ |
319 m_quick_two_sum(s0,s0, c2, s1); \ |
320 if (s1 != 0.0) { \ |
320 if (s1 != 0.0) { \ |
321 m_quick_two_sum(s1,s1, c3, s2); \ |
321 m_quick_two_sum(s1,s1, c3, s2); \ |
322 if (s2 != 0.0) {\ |
322 if (s2 != 0.0) {\ |
323 m_quick_two_sum(s2,s2, c4, s3); \ |
323 m_quick_two_sum(s2,s2, c4, s3); \ |
324 } else { \ |
324 } else { \ |
325 m_quick_two_sum(s1 ,s1, c4, s2); \ |
325 m_quick_two_sum(s1 ,s1, c4, s2); \ |
326 } \ |
326 } \ |
327 } else { \ |
327 } else { \ |
328 m_quick_two_sum(s0,s0, c3, s1); \ |
328 m_quick_two_sum(s0,s0, c3, s1); \ |
329 if (s1 != 0.0) { \ |
329 if (s1 != 0.0) { \ |
330 m_quick_two_sum(s1,s1, c4, s2); \ |
330 m_quick_two_sum(s1,s1, c4, s2); \ |
331 } else { \ |
331 } else { \ |
332 m_quick_two_sum(s0,s0, c4, s1); \ |
332 m_quick_two_sum(s0,s0, c4, s1); \ |
333 } \ |
333 } \ |
334 } \ |
334 } \ |
335 } \ |
335 } \ |
336 \ |
336 \ |
337 c0 = s0; \ |
337 c0 = s0; \ |
338 c1 = s1; \ |
338 c1 = s1; \ |
339 c2 = s2; \ |
339 c2 = s2; \ |
340 c3 = s3; \ |
340 c3 = s3; \ |
341 } \ |
341 } \ |
342 } |
342 } |
343 |
343 |
344 %} |
344 %} |
345 ! ! |
345 ! ! |
347 !QDouble primitiveFunctions! |
347 !QDouble primitiveFunctions! |
348 %{ |
348 %{ |
349 |
349 |
350 /*********** Basic Functions ************/ |
350 /*********** Basic Functions ************/ |
351 /* Computes fl(a+b) and err(a+b). Assumes |a| >= |b|. */ |
351 /* Computes fl(a+b) and err(a+b). Assumes |a| >= |b|. */ |
352 inline double |
352 inline double |
353 quick_two_sum(double a, double b, double *errPtr) { |
353 quick_two_sum(double a, double b, double *errPtr) { |
354 double s = a + b; |
354 double s = a + b; |
355 *errPtr = b - (s - a); |
355 *errPtr = b - (s - a); |
356 return s; |
356 return s; |
357 } |
357 } |
358 |
358 |
359 /* Computes fl(a-b) and err(a-b). Assumes |a| >= |b| */ |
359 /* Computes fl(a-b) and err(a-b). Assumes |a| >= |b| */ |
360 inline double |
360 inline double |
361 quick_two_diff(double a, double b, double *errPtr) { |
361 quick_two_diff(double a, double b, double *errPtr) { |
362 double s = a - b; |
362 double s = a - b; |
363 *errPtr = (a - s) - b; |
363 *errPtr = (a - s) - b; |
364 return s; |
364 return s; |
365 } |
365 } |
366 |
366 |
367 /* Computes fl(a+b) and err(a+b). */ |
367 /* Computes fl(a+b) and err(a+b). */ |
368 inline double |
368 inline double |
369 two_sum(double a, double b, double *errPtr) { |
369 two_sum(double a, double b, double *errPtr) { |
370 double s = a + b; |
370 double s = a + b; |
371 double bb = s - a; |
371 double bb = s - a; |
372 *errPtr = (a - (s - bb)) + (b - bb); |
372 *errPtr = (a - (s - bb)) + (b - bb); |
373 return s; |
373 return s; |
374 } |
374 } |
375 |
375 |
376 /* Computes fl(a-b) and err(a-b). */ |
376 /* Computes fl(a-b) and err(a-b). */ |
377 inline double |
377 inline double |
378 two_diff(double a, double b, double *errPtr) { |
378 two_diff(double a, double b, double *errPtr) { |
379 double s = a - b; |
379 double s = a - b; |
380 double bb = s - a; |
380 double bb = s - a; |
381 *errPtr = (a - (s - bb)) - (b + bb); |
381 *errPtr = (a - (s - bb)) - (b + bb); |
382 return s; |
382 return s; |
383 } |
383 } |
384 |
384 |
385 #ifndef QD_FMS |
385 #ifndef QD_FMS |
386 /* Computes high word and lo word of a */ |
386 /* Computes high word and lo word of a */ |
387 inline void |
387 inline void |
388 split(double a, double *hiPtr, double *loPtr) { |
388 split(double a, double *hiPtr, double *loPtr) { |
389 double temp; |
389 double temp; |
390 if (a > _QD_SPLIT_THRESH || a < -_QD_SPLIT_THRESH) { |
390 if (a > _QD_SPLIT_THRESH || a < -_QD_SPLIT_THRESH) { |
391 a *= 3.7252902984619140625e-09; // 2^-28 |
391 a *= 3.7252902984619140625e-09; // 2^-28 |
392 temp = _QD_SPLITTER * a; |
392 temp = _QD_SPLITTER * a; |
401 } |
401 } |
402 } |
402 } |
403 #endif |
403 #endif |
404 |
404 |
405 /* Computes fl(a*b) and err(a*b). */ |
405 /* Computes fl(a*b) and err(a*b). */ |
406 inline double |
406 inline double |
407 two_prod(double a, double b, double *errPtr) { |
407 two_prod(double a, double b, double *errPtr) { |
408 #ifdef QD_FMS |
408 #ifdef QD_FMS |
409 double p = a * b; |
409 double p = a * b; |
410 *errPtr = QD_FMS(a, b, p); |
410 *errPtr = QD_FMS(a, b, p); |
411 return p; |
411 return p; |
418 return p; |
418 return p; |
419 #endif |
419 #endif |
420 } |
420 } |
421 |
421 |
422 /* Computes fl(a*a) and err(a*a). Faster than the above method. */ |
422 /* Computes fl(a*a) and err(a*a). Faster than the above method. */ |
423 inline double |
423 inline double |
424 two_sqr(double a, double *errPtr) { |
424 two_sqr(double a, double *errPtr) { |
425 #ifdef QD_FMS |
425 #ifdef QD_FMS |
426 double p = a * a; |
426 double p = a * a; |
427 *errPtr = QD_FMS(a, a, p); |
427 *errPtr = QD_FMS(a, a, p); |
428 return p; |
428 return p; |
434 return q; |
434 return q; |
435 #endif |
435 #endif |
436 } |
436 } |
437 |
437 |
438 /* Computes the nearest integer to d. */ |
438 /* Computes the nearest integer to d. */ |
439 inline double |
439 inline double |
440 nint(double d) { |
440 nint(double d) { |
441 if (d == floor(d)) |
441 if (d == floor(d)) |
442 return d; |
442 return d; |
443 return floor(d + 0.5); |
443 return floor(d + 0.5); |
444 } |
444 } |
445 |
445 |
446 /* Computes the truncated integer. */ |
446 /* Computes the truncated integer. */ |
447 inline double |
447 inline double |
448 aint(double d) { |
448 aint(double d) { |
449 return (d >= 0.0) ? floor(d) : ceil(d); |
449 return (d >= 0.0) ? floor(d) : ceil(d); |
450 } |
450 } |
451 |
451 |
452 inline void |
452 inline void |
453 renorm4(double *c0Ptr, double *c1Ptr, double *c2Ptr, double *c3Ptr) { |
453 renorm4(double *c0Ptr, double *c1Ptr, double *c2Ptr, double *c3Ptr) { |
454 double s0, s1, s2 = 0.0, s3 = 0.0; |
454 double s0, s1, s2 = 0.0, s3 = 0.0; |
455 double c0 = *c0Ptr; |
455 double c0 = *c0Ptr; |
456 |
456 |
457 if (isinf(c0)) return; |
457 if (isinf(c0)) return; |
458 |
458 |
459 s0 = quick_two_sum(*c2Ptr, *c3Ptr, c3Ptr); |
459 s0 = quick_two_sum(*c2Ptr, *c3Ptr, c3Ptr); |
460 s0 = quick_two_sum(*c1Ptr, s0, c2Ptr); |
460 s0 = quick_two_sum(*c1Ptr, s0, c2Ptr); |
461 c0 = quick_two_sum(c0, s0, c1Ptr); |
461 c0 = quick_two_sum(c0, s0, c1Ptr); |
480 *c1Ptr = s1; |
480 *c1Ptr = s1; |
481 *c2Ptr = s2; |
481 *c2Ptr = s2; |
482 *c3Ptr = s3; |
482 *c3Ptr = s3; |
483 } |
483 } |
484 |
484 |
485 inline void |
485 inline void |
486 renorm5(double *c0Ptr, double *c1Ptr, double *c2Ptr, double *c3Ptr, double *c4Ptr) { |
486 renorm5(double *c0Ptr, double *c1Ptr, double *c2Ptr, double *c3Ptr, double *c4Ptr) { |
487 double s0, s1, s2 = 0.0, s3 = 0.0; |
487 double s0, s1, s2 = 0.0, s3 = 0.0; |
488 |
488 |
489 if (isinf(*c0Ptr)) return; |
489 if (isinf(*c0Ptr)) return; |
490 |
490 |
491 s0 = quick_two_sum(*c3Ptr, *c4Ptr, c4Ptr); |
491 s0 = quick_two_sum(*c3Ptr, *c4Ptr, c4Ptr); |
492 s0 = quick_two_sum(*c2Ptr, s0, c3Ptr); |
492 s0 = quick_two_sum(*c2Ptr, s0, c3Ptr); |
493 s0 = quick_two_sum(*c1Ptr, s0, c2Ptr); |
493 s0 = quick_two_sum(*c1Ptr, s0, c2Ptr); |
500 if (s1 != 0.0) { |
500 if (s1 != 0.0) { |
501 s1 = quick_two_sum(s1, *c2Ptr, &s2); |
501 s1 = quick_two_sum(s1, *c2Ptr, &s2); |
502 if (s2 != 0.0) { |
502 if (s2 != 0.0) { |
503 s2 =quick_two_sum(s2, *c3Ptr, &s3); |
503 s2 =quick_two_sum(s2, *c3Ptr, &s3); |
504 if (s3 != 0.0) |
504 if (s3 != 0.0) |
505 s3 += *c4Ptr; |
505 s3 += *c4Ptr; |
506 else |
506 else |
507 s2 += *c4Ptr; |
507 s2 += *c4Ptr; |
508 } else { |
508 } else { |
509 s1 = quick_two_sum(s1, *c3Ptr, &s2); |
509 s1 = quick_two_sum(s1, *c3Ptr, &s2); |
510 if (s2 != 0.0) |
510 if (s2 != 0.0) |
511 s2 = quick_two_sum(s2, *c4Ptr, &s3); |
511 s2 = quick_two_sum(s2, *c4Ptr, &s3); |
512 else |
512 else |
513 s1 = quick_two_sum(s1, *c4Ptr, &s2); |
513 s1 = quick_two_sum(s1, *c4Ptr, &s2); |
514 } |
514 } |
515 } else { |
515 } else { |
516 s0 = quick_two_sum(s0, *c2Ptr, &s1); |
516 s0 = quick_two_sum(s0, *c2Ptr, &s1); |
517 if (s1 != 0.0) { |
517 if (s1 != 0.0) { |
518 s1 = quick_two_sum(s1, *c3Ptr, &s2); |
518 s1 = quick_two_sum(s1, *c3Ptr, &s2); |
519 if (s2 != 0.0) |
519 if (s2 != 0.0) |
520 s2 = quick_two_sum(s2, *c4Ptr, &s3); |
520 s2 = quick_two_sum(s2, *c4Ptr, &s3); |
521 else |
521 else |
522 s1 = quick_two_sum(s1, *c4Ptr, &s2); |
522 s1 = quick_two_sum(s1, *c4Ptr, &s2); |
523 } else { |
523 } else { |
524 s0 = quick_two_sum(s0, *c3Ptr, &s1); |
524 s0 = quick_two_sum(s0, *c3Ptr, &s1); |
525 if (s1 != 0.0) |
525 if (s1 != 0.0) |
526 s1 = quick_two_sum(s1, *c4Ptr, &s2); |
526 s1 = quick_two_sum(s1, *c4Ptr, &s2); |
527 else |
527 else |
528 s0 = quick_two_sum(s0, *c4Ptr, &s1); |
528 s0 = quick_two_sum(s0, *c4Ptr, &s1); |
529 } |
529 } |
530 } |
530 } |
531 |
531 |
532 *c0Ptr = s0; |
532 *c0Ptr = s0; |
533 *c1Ptr = s1; |
533 *c1Ptr = s1; |
534 *c2Ptr = s2; |
534 *c2Ptr = s2; |
535 *c3Ptr = s3; |
535 *c3Ptr = s3; |
536 } |
536 } |
537 |
537 |
538 inline void |
538 inline void |
539 three_sum(double *aPtr, double *bPtr, double *cPtr) { |
539 three_sum(double *aPtr, double *bPtr, double *cPtr) { |
540 double t1, t2, t3; |
540 double t1, t2, t3; |
541 t1 = two_sum(*aPtr, *bPtr, &t2); |
541 t1 = two_sum(*aPtr, *bPtr, &t2); |
542 *aPtr = two_sum(*cPtr, t1, &t3); |
542 *aPtr = two_sum(*cPtr, t1, &t3); |
543 *bPtr = two_sum(t2, t3, cPtr); |
543 *bPtr = two_sum(t2, t3, cPtr); |
550 *bPtr = t2 + t3; |
550 *bPtr = t2 + t3; |
551 } |
551 } |
552 |
552 |
553 |
553 |
554 #if 0 |
554 #if 0 |
555 /* These are provided to give consistent |
555 /* These are provided to give consistent |
556 interface for double with double-double and quad-double. */ |
556 interface for double with double-double and quad-double. */ |
557 inline void |
557 inline void |
558 sincosh(double t, double &sinh_t, double &cosh_t) { |
558 sincosh(double t, double &sinh_t, double &cosh_t) { |
559 sinh_t = sinh(t); |
559 sinh_t = sinh(t); |
560 cosh_t = cosh(t); |
560 cosh_t = cosh(t); |
561 } |
561 } |
562 |
562 |
563 inline double |
563 inline double |
564 sqr(double t) { |
564 sqr(double t) { |
565 return t * t; |
565 return t * t; |
566 } |
566 } |
567 |
567 |
568 inline double |
568 inline double |
569 to_double(double a) { |
569 to_double(double a) { |
570 return a; |
570 return a; |
571 } |
571 } |
572 |
572 |
573 inline int |
573 inline int |
574 to_int(double a) { |
574 to_int(double a) { |
575 return static_cast<int>(a); |
575 return static_cast<int>(a); |
576 } |
576 } |
577 #endif |
577 #endif |
578 |
578 |
579 %} |
579 %} |
580 ! ! |
580 ! ! |
582 !QDouble class methodsFor:'documentation'! |
582 !QDouble class methodsFor:'documentation'! |
583 |
583 |
584 copyright |
584 copyright |
585 " |
585 " |
586 COPYRIGHT (c) 2017 by eXept Software AG |
586 COPYRIGHT (c) 2017 by eXept Software AG |
587 All Rights Reserved |
587 All Rights Reserved |
588 |
588 |
589 This software is furnished under a license and may be used |
589 This software is furnished under a license and may be used |
590 only in accordance with the terms of that license and with the |
590 only in accordance with the terms of that license and with the |
591 inclusion of the above copyright notice. This software may not |
591 inclusion of the above copyright notice. This software may not |
592 be provided or otherwise made available to, or used by, any |
592 be provided or otherwise made available to, or used by, any |
601 |
601 |
602 In contrast to Floats (which use the C-compilers native 64bit 'double' format), |
602 In contrast to Floats (which use the C-compilers native 64bit 'double' format), |
603 QDoubles give you 212 bit or approx. 64 decimal digits of precision. |
603 QDoubles give you 212 bit or approx. 64 decimal digits of precision. |
604 |
604 |
605 Representation: |
605 Representation: |
606 QDoubles use 4 IEEE doubles, each keeping 53 bits of precision. |
606 QDoubles use 4 IEEE doubles, each keeping 53 bits of precision. |
607 |
607 |
608 Range and Precision of Storage Formats: see LimitedPrecisionReal >> documentation |
608 Range and Precision of Storage Formats: see LimitedPrecisionReal >> documentation |
609 |
609 |
610 [author:] |
610 [author:] |
611 Claus Gittinger |
611 Claus Gittinger |
612 |
612 |
613 [see also:] |
613 [see also:] |
614 Number |
614 Number |
615 Float ShortFloat Fraction FixedPoint Integer Complex |
615 Float ShortFloat Fraction FixedPoint Integer Complex |
616 FloatArray DoubleArray |
616 FloatArray DoubleArray |
617 " |
617 " |
618 ! ! |
618 ! ! |
619 |
619 |
620 !QDouble class methodsFor:'instance creation'! |
620 !QDouble class methodsFor:'instance creation'! |
621 |
621 |
632 #ifdef __SCHTEAM__ |
632 #ifdef __SCHTEAM__ |
633 ERROR("trying to instantiate a quad double"); |
633 ERROR("trying to instantiate a quad double"); |
634 #else |
634 #else |
635 OBJ newFloat; |
635 OBJ newFloat; |
636 printf("xxx\n"); |
636 printf("xxx\n"); |
637 __qNew(newFloat, sizeof(struct __quadDoubleStruct)); |
637 __qNew(newFloat, sizeof(struct __quadDoubleStruct)); |
638 __stx_setClass(newFloat, QDouble); |
638 __stx_setClass(newFloat, QDouble); |
639 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[0] = 0.0; |
639 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[0] = 0.0; |
640 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[1] = 0.0; |
640 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[1] = 0.0; |
641 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[2] = 0.0; |
641 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[2] = 0.0; |
642 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[3] = 0.0; |
642 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[3] = 0.0; |
643 RETURN (newFloat); |
643 RETURN (newFloat); |
644 #endif /* not SCHTEAM */ |
644 #endif /* not SCHTEAM */ |
645 %} |
645 %} |
646 |
646 |
647 " |
647 " |
658 #ifdef __SCHTEAM__ |
658 #ifdef __SCHTEAM__ |
659 ERROR("trying to instantiate a quad double"); |
659 ERROR("trying to instantiate a quad double"); |
660 #else |
660 #else |
661 OBJ newQD; |
661 OBJ newQD; |
662 |
662 |
663 if (__isFloatLike(d0) |
663 if (__isFloatLike(d0) |
664 && __isFloatLike(d1) |
664 && __isFloatLike(d1) |
665 && __isFloatLike(d2) |
665 && __isFloatLike(d2) |
666 && __isFloatLike(d3)) { |
666 && __isFloatLike(d3)) { |
667 __qNew_qdReal(newQD, __floatVal(d0), __floatVal(d1), |
667 __qNew_qdReal(newQD, __floatVal(d0), __floatVal(d1), |
668 __floatVal(d2), __floatVal(d3)); |
668 __floatVal(d2), __floatVal(d3)); |
669 RETURN (newQD); |
669 RETURN (newQD); |
670 } |
670 } |
671 #endif |
671 #endif |
672 %}. |
672 %}. |
673 self error:'invalid argument' |
673 self error:'invalid argument' |
674 |
674 |
675 " |
675 " |
676 self d0: 3.141592653589793116e+00 |
676 self d0: 3.141592653589793116e+00 |
677 d1: 1.224646799147353207e-16 |
677 d1: 1.224646799147353207e-16 |
678 d2: -2.994769809718339666e-33 |
678 d2: -2.994769809718339666e-33 |
679 d3: 1.112454220863365282e-49 |
679 d3: 1.112454220863365282e-49 |
680 " |
680 " |
681 |
681 |
682 "Created: / 12-06-2017 / 20:17:14 / cg" |
682 "Created: / 12-06-2017 / 20:17:14 / cg" |
683 ! |
683 ! |
684 |
684 |
689 #ifdef __SCHTEAM__ |
689 #ifdef __SCHTEAM__ |
690 ERROR("trying to instantiate a quad double"); |
690 ERROR("trying to instantiate a quad double"); |
691 #else |
691 #else |
692 OBJ newQD; |
692 OBJ newQD; |
693 |
693 |
694 if (__isDoubleArray(aDoubleArray)) { |
694 if (__isDoubleArray(aDoubleArray)) { |
695 __qNew_qdReal(newQD, |
695 __qNew_qdReal(newQD, |
696 __DoubleArrayInstPtr(aDoubleArray)->d_element[0], |
696 __DoubleArrayInstPtr(aDoubleArray)->d_element[0], |
697 __DoubleArrayInstPtr(aDoubleArray)->d_element[1], |
697 __DoubleArrayInstPtr(aDoubleArray)->d_element[1], |
698 __DoubleArrayInstPtr(aDoubleArray)->d_element[2], |
698 __DoubleArrayInstPtr(aDoubleArray)->d_element[2], |
699 __DoubleArrayInstPtr(aDoubleArray)->d_element[3]); |
699 __DoubleArrayInstPtr(aDoubleArray)->d_element[3]); |
700 RETURN (newQD); |
700 RETURN (newQD); |
701 } |
701 } |
702 #endif |
702 #endif |
703 %}. |
703 %}. |
704 self error:'invalid argument' |
704 self error:'invalid argument' |
705 |
705 |
706 " |
706 " |
707 self fromDoubleArray(DoubleArray |
707 self fromDoubleArray(DoubleArray |
708 with: 3.141592653589793116e+00 |
708 with: 3.141592653589793116e+00 |
709 with: 1.224646799147353207e-16 |
709 with: 1.224646799147353207e-16 |
710 with: -2.994769809718339666e-33 |
710 with: -2.994769809718339666e-33 |
711 with: 1.112454220863365282e-49) |
711 with: 1.112454220863365282e-49) |
712 " |
712 " |
713 |
713 |
714 "Created: / 12-06-2017 / 18:25:32 / cg" |
714 "Created: / 12-06-2017 / 18:25:32 / cg" |
715 ! |
715 ! |
716 |
716 |
723 #else |
723 #else |
724 double dVal; |
724 double dVal; |
725 OBJ newFloat; |
725 OBJ newFloat; |
726 |
726 |
727 if (__isFloatLike(aFloat)) { |
727 if (__isFloatLike(aFloat)) { |
728 dVal = __floatVal(aFloat); |
728 dVal = __floatVal(aFloat); |
729 } else if (__isShortFloat(aFloat)) { |
729 } else if (__isShortFloat(aFloat)) { |
730 dVal = __shortFloatVal(aFloat); |
730 dVal = __shortFloatVal(aFloat); |
731 } else { |
731 } else { |
732 goto badArg; |
732 goto badArg; |
733 } |
733 } |
734 |
734 |
735 __qNew(newFloat, sizeof(struct __quadDoubleStruct)); |
735 __qNew(newFloat, sizeof(struct __quadDoubleStruct)); |
736 __stx_setClass(newFloat, QDouble); |
736 __stx_setClass(newFloat, QDouble); |
737 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[0] = dVal; |
737 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[0] = dVal; |
738 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[1] = 0.0; |
738 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[1] = 0.0; |
739 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[2] = 0.0; |
739 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[2] = 0.0; |
740 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[3] = 0.0; |
740 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[3] = 0.0; |
741 RETURN (newFloat); |
741 RETURN (newFloat); |
742 |
742 |
743 badArg: ; |
743 badArg: ; |
744 |
744 |
745 #endif |
745 #endif |
759 %{ /* NOCONTEXT */ |
759 %{ /* NOCONTEXT */ |
760 #ifndef __SCHTEAM__ |
760 #ifndef __SCHTEAM__ |
761 OBJ newFloat; |
761 OBJ newFloat; |
762 |
762 |
763 if (__isSmallInteger(anInteger)) { |
763 if (__isSmallInteger(anInteger)) { |
764 __qNew(newFloat, sizeof(struct __quadDoubleStruct)); |
764 __qNew(newFloat, sizeof(struct __quadDoubleStruct)); |
765 __stx_setClass(newFloat, QDouble); |
765 __stx_setClass(newFloat, QDouble); |
766 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[0] = (double)(__smallIntegerVal(anInteger)); |
766 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[0] = (double)(__smallIntegerVal(anInteger)); |
767 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[1] = 0.0; |
767 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[1] = 0.0; |
768 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[2] = 0.0; |
768 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[2] = 0.0; |
769 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[3] = 0.0; |
769 __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[3] = 0.0; |
770 RETURN (newFloat); |
770 RETURN (newFloat); |
771 } |
771 } |
772 #endif |
772 #endif |
773 %}. |
773 %}. |
774 ^ super fromInteger:anInteger |
774 ^ super fromInteger:anInteger |
775 |
775 |
785 e |
785 e |
786 "return the constant e as quad precision double. |
786 "return the constant e as quad precision double. |
787 (returns approx. 212 bits of precision)" |
787 (returns approx. 212 bits of precision)" |
788 |
788 |
789 E isNil ifTrue:[ |
789 E isNil ifTrue:[ |
790 E := self fromDoubleArray(DoubleArray |
790 E := self fromDoubleArray:(DoubleArray |
791 with: 2.718281828459045091e+00 |
791 with: 2.718281828459045091e+00 |
792 with: 1.445646891729250158e-16 |
792 with: 1.445646891729250158e-16 |
793 with: -2.127717108038176765e-33 |
793 with: -2.127717108038176765e-33 |
794 with: 1.515630159841218954e-49) |
794 with: 1.515630159841218954e-49) |
795 ]. |
795 ]. |
796 ^ E |
796 ^ E |
797 |
797 |
798 " |
798 " |
799 self e |
799 self e |
800 " |
800 " |
805 ln10 |
805 ln10 |
806 "return the constant e as quad precision double. |
806 "return the constant e as quad precision double. |
807 (returns approx. 212 bits of precision)" |
807 (returns approx. 212 bits of precision)" |
808 |
808 |
809 Ln10 isNil ifTrue:[ |
809 Ln10 isNil ifTrue:[ |
810 Ln10 := self fromDoubleArray(DoubleArray |
810 Ln10 := self fromDoubleArray:(DoubleArray |
811 with: 2.302585092994045901e+00 |
811 with: 2.302585092994045901e+00 |
812 with: -2.170756223382249351e-16 |
812 with: -2.170756223382249351e-16 |
813 with: -9.984262454465776570e-33 |
813 with: -9.984262454465776570e-33 |
814 with: -4.023357454450206379e-49) |
814 with: -4.023357454450206379e-49) |
815 ]. |
815 ]. |
816 ^ Ln10 |
816 ^ Ln10 |
817 |
817 |
818 " |
818 " |
819 self ln10 |
819 self ln10 |
820 " |
820 " |
825 ln2 |
825 ln2 |
826 "return the constant e as quad precision double. |
826 "return the constant e as quad precision double. |
827 (returns approx. 212 bits of precision)" |
827 (returns approx. 212 bits of precision)" |
828 |
828 |
829 Ln2 isNil ifTrue:[ |
829 Ln2 isNil ifTrue:[ |
830 Ln2 := self fromDoubleArray(DoubleArray |
830 Ln2 := self fromDoubleArray:(DoubleArray |
831 with: 6.931471805599452862e-01 |
831 with: 6.931471805599452862e-01 |
832 with: 2.319046813846299558e-17 |
832 with: 2.319046813846299558e-17 |
833 with: 5.707708438416212066e-34 |
833 with: 5.707708438416212066e-34 |
834 with: -3.582432210601811423e-50) |
834 with: -3.582432210601811423e-50) |
835 ]. |
835 ]. |
836 ^ Ln2 |
836 ^ Ln2 |
837 |
837 |
838 " |
838 " |
839 self ln2 |
839 self ln2 |
840 " |
840 " |
845 pi |
845 pi |
846 "return the constant pi as quad precision double. |
846 "return the constant pi as quad precision double. |
847 (returns approx. 212 bits of precision)" |
847 (returns approx. 212 bits of precision)" |
848 |
848 |
849 Pi isNil ifTrue:[ |
849 Pi isNil ifTrue:[ |
850 Pi := self fromDoubleArray(DoubleArray |
850 Pi := self fromDoubleArray:(DoubleArray |
851 with: 3.141592653589793116e+00 |
851 with: 3.141592653589793116e+00 |
852 with: 1.224646799147353207e-16 |
852 with: 1.224646799147353207e-16 |
853 with: -2.994769809718339666e-33 |
853 with: -2.994769809718339666e-33 |
854 with: 1.112454220863365282e-49) |
854 with: 1.112454220863365282e-49) |
855 ]. |
855 ]. |
856 ^ Pi |
856 ^ Pi |
857 |
857 |
858 " |
858 " |
859 self pi |
859 self pi |
860 " |
860 " |
893 |
893 |
894 numBitsInMantissa |
894 numBitsInMantissa |
895 "answer the number of bits in the mantissa" |
895 "answer the number of bits in the mantissa" |
896 |
896 |
897 ^ Float precision * 4 |
897 ^ Float precision * 4 |
898 |
898 |
899 " |
899 " |
900 1.0 class numBitsInMantissa |
900 1.0 class numBitsInMantissa |
901 1.0 asShortFloat class numBitsInMantissa |
901 1.0 asShortFloat class numBitsInMantissa |
902 1.0 asLongFloat class numBitsInMantissa |
902 1.0 asLongFloat class numBitsInMantissa |
903 1.0 asDDouble class numBitsInMantissa |
903 1.0 asDDouble class numBitsInMantissa |
914 |
914 |
915 precision |
915 precision |
916 "answer the number of bits in the mantissa" |
916 "answer the number of bits in the mantissa" |
917 |
917 |
918 ^ Float precision * 4 |
918 ^ Float precision * 4 |
919 |
919 |
920 " |
920 " |
921 1.0 class numBitsInMantissa |
921 1.0 class numBitsInMantissa |
922 1.0 asShortFloat class numBitsInMantissa |
922 1.0 asShortFloat class numBitsInMantissa |
923 1.0 asLongFloat class numBitsInMantissa |
923 1.0 asLongFloat class numBitsInMantissa |
924 1.0 asDDouble class numBitsInMantissa |
924 1.0 asDDouble class numBitsInMantissa |
998 ! ! |
998 ! ! |
999 |
999 |
1000 !QDouble methodsFor:'coercing & converting'! |
1000 !QDouble methodsFor:'coercing & converting'! |
1001 |
1001 |
1002 asDoubleArray |
1002 asDoubleArray |
1003 ^ DoubleArray |
1003 ^ DoubleArray |
1004 with:self d0 |
1004 with:self d0 |
1005 with:self d1 |
1005 with:self d1 |
1006 with:self d2 |
1006 with:self d2 |
1007 with:self d3. |
1007 with:self d3. |
1008 |
1008 |
1009 " |
1009 " |
1010 (QDouble fromFloat:1.0) asDoubleArray |
1010 (QDouble fromFloat:1.0) asDoubleArray |
1011 (QDouble fromFloat:2.0) asDoubleArray |
1011 (QDouble fromFloat:2.0) asDoubleArray |
1012 " |
1012 " |
1089 |
1089 |
1090 !QDouble methodsFor:'double dispatching'! |
1090 !QDouble methodsFor:'double dispatching'! |
1091 |
1091 |
1092 differenceFromFloat:aFloat |
1092 differenceFromFloat:aFloat |
1093 "aFloat - self" |
1093 "aFloat - self" |
1094 |
1094 |
1095 ^ aFloat + (self negated) |
1095 ^ aFloat + (self negated) |
1096 |
1096 |
1097 " |
1097 " |
1098 1.0 - (QDouble fromFloat:1.0) |
1098 1.0 - (QDouble fromFloat:1.0) |
1099 1e20 - (QDouble fromFloat:1.0) |
1099 1e20 - (QDouble fromFloat:1.0) |
1108 "Created: / 12-06-2017 / 23:38:05 / cg" |
1108 "Created: / 12-06-2017 / 23:38:05 / cg" |
1109 ! |
1109 ! |
1110 |
1110 |
1111 differenceFromQDouble:aQDouble |
1111 differenceFromQDouble:aQDouble |
1112 "aQDouble - self" |
1112 "aQDouble - self" |
1113 |
1113 |
1114 ^ aQDouble + (self negated) |
1114 ^ aQDouble + (self negated) |
1115 |
1115 |
1116 " |
1116 " |
1117 1.0 - (QDouble fromFloat:1.0) |
1117 1.0 - (QDouble fromFloat:1.0) |
1118 1e20 - (QDouble fromFloat:1.0) |
1118 1e20 - (QDouble fromFloat:1.0) |
1128 ! |
1128 ! |
1129 |
1129 |
1130 equalFromQDouble:aQDouble |
1130 equalFromQDouble:aQDouble |
1131 %{ |
1131 %{ |
1132 if (__Class(aQDouble) == QDouble) { |
1132 if (__Class(aQDouble) == QDouble) { |
1133 double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue; |
1133 double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue; |
1134 double *b = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue; |
1134 double *b = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue; |
1135 |
1135 |
1136 RETURN ((a[0] == b[0] |
1136 RETURN ((a[0] == b[0] |
1137 && a[1] == b[1] |
1137 && a[1] == b[1] |
1138 && a[2] == b[2] |
1138 && a[2] == b[2] |
1139 && a[3] == b[3]) ? true : false); |
1139 && a[3] == b[3]) ? true : false); |
1140 } |
1140 } |
1141 %}. |
1141 %}. |
1142 ^ (aQDouble d0 = self d0) |
1142 ^ (aQDouble d0 = self d0) |
1143 and:[ (aQDouble d1 = self d1) |
1143 and:[ (aQDouble d1 = self d1) |
1144 and:[ (aQDouble d2 = self d2) |
1144 and:[ (aQDouble d2 = self d2) |
1145 and:[ (aQDouble d3 = self d3) ]]] |
1145 and:[ (aQDouble d3 = self d3) ]]] |
1146 |
1146 |
1147 " |
1147 " |
1148 (QDouble fromFloat:1.0) = (QDouble fromFloat:1.0) |
1148 (QDouble fromFloat:1.0) = (QDouble fromFloat:1.0) |
1149 (QDouble fromFloat:1.0) = 1.0 |
1149 (QDouble fromFloat:1.0) = 1.0 |
1150 1.0 = (QDouble fromFloat:1.0) |
1150 1.0 = (QDouble fromFloat:1.0) |
1151 " |
1151 " |
1158 "sent when aQDouble does not know how to compare to the receiver.. |
1158 "sent when aQDouble does not know how to compare to the receiver.. |
1159 Return true if aQDouble < self" |
1159 Return true if aQDouble < self" |
1160 |
1160 |
1161 %{ |
1161 %{ |
1162 if (__Class(aQDouble) == QDouble) { |
1162 if (__Class(aQDouble) == QDouble) { |
1163 double *a = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue; |
1163 double *a = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue; |
1164 double *b = __QuadDoubleInstPtr(self)->d_quadDoubleValue; |
1164 double *b = __QuadDoubleInstPtr(self)->d_quadDoubleValue; |
1165 |
1165 |
1166 // now compare if a < b! |
1166 // now compare if a < b! |
1167 RETURN |
1167 RETURN |
1168 ((a[0] < b[0] || |
1168 ((a[0] < b[0] || |
1169 (a[0] == b[0] && (a[1] < b[1] || |
1169 (a[0] == b[0] && (a[1] < b[1] || |
1170 (a[1] == b[1] && (a[2] < b[2] || |
1170 (a[1] == b[1] && (a[2] < b[2] || |
1171 (a[2] == b[2] && a[3] < b[3])))))) ? true : false); |
1171 (a[2] == b[2] && a[3] < b[3])))))) ? true : false); |
1172 } |
1172 } |
1173 %}. |
1173 %}. |
1174 ^ super lessFromQDouble:aQDouble |
1174 ^ super lessFromQDouble:aQDouble |
1175 |
1175 |
1176 " |
1176 " |
1188 ! |
1188 ! |
1189 |
1189 |
1190 productFromFloat:aFloat |
1190 productFromFloat:aFloat |
1191 %{ |
1191 %{ |
1192 if (__isFloatLike(aFloat)) { |
1192 if (__isFloatLike(aFloat)) { |
1193 double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue; |
1193 double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue; |
1194 double b = __floatVal(aFloat); |
1194 double b = __floatVal(aFloat); |
1195 double p0, p1, p2, p3; |
1195 double p0, p1, p2, p3; |
1196 double q0, q1, q2; |
1196 double q0, q1, q2; |
1197 double s0, s1, s2, s3, s4; |
1197 double s0, s1, s2, s3, s4; |
1198 OBJ newQD; |
1198 OBJ newQD; |
1199 int savedCV; |
1199 int savedCV; |
1200 |
1200 |
1201 fpu_fix_start(&savedCV); |
1201 fpu_fix_start(&savedCV); |
1202 |
1202 |
1203 m_two_prod(p0, a[0], b, q0); |
1203 m_two_prod(p0, a[0], b, q0); |
1204 m_two_prod(p1, a[1], b, q1); |
1204 m_two_prod(p1, a[1], b, q1); |
1205 m_two_prod(p2, a[2], b, q2); |
1205 m_two_prod(p2, a[2], b, q2); |
1206 p3 = a[3] * b; |
1206 p3 = a[3] * b; |
1207 |
1207 |
1208 s0 = p0; |
1208 s0 = p0; |
1209 |
1209 |
1210 m_two_sum(s1, q0, p1, s2); |
1210 m_two_sum(s1, q0, p1, s2); |
1211 |
1211 |
1212 m_three_sum(s2, q1, p2); |
1212 m_three_sum(s2, q1, p2); |
1213 |
1213 |
1214 m_three_sum2(q1, q2, p3); |
1214 m_three_sum2(q1, q2, p3); |
1215 s3 = q1; |
1215 s3 = q1; |
1216 |
1216 |
1217 s4 = q2 + p2; |
1217 s4 = q2 + p2; |
1218 |
1218 |
1219 m_renorm5(s0, s1, s2, s3, s4); |
1219 m_renorm5(s0, s1, s2, s3, s4); |
1220 fpu_fix_end(&savedCV); |
1220 fpu_fix_end(&savedCV); |
1221 |
1221 |
1222 __qNew_qdReal(newQD, s0, s1, s2, s3); |
1222 __qNew_qdReal(newQD, s0, s1, s2, s3); |
1223 RETURN( newQD ); |
1223 RETURN( newQD ); |
1224 } |
1224 } |
1225 %}. |
1225 %}. |
1226 ^ super productFromFloat:aFloat. |
1226 ^ super productFromFloat:aFloat. |
1227 |
1227 |
1228 " |
1228 " |
1230 ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) productFromFloat:2.0 |
1230 ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) productFromFloat:2.0 |
1231 ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) productFromFloat:2e20 |
1231 ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) productFromFloat:2e20 |
1232 |
1232 |
1233 2.0 * (QDouble fromFloat:1.0) |
1233 2.0 * (QDouble fromFloat:1.0) |
1234 2.0 * (QDouble fromFloat:3.0) |
1234 2.0 * (QDouble fromFloat:3.0) |
1235 |
1235 |
1236 2.0 * ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) |
1236 2.0 * ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) |
1237 (2.0 * ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0))) - (QDouble fromFloat:1e20) - (QDouble fromFloat:1e20) |
1237 (2.0 * ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0))) - (QDouble fromFloat:1e20) - (QDouble fromFloat:1e20) |
1238 |
1238 |
1239 (2.0 * (QDouble fromFloat:1.0)) asFloat |
1239 (2.0 * (QDouble fromFloat:1.0)) asFloat |
1240 (1e20 * (QDouble fromFloat:1.0)) asFloat |
1240 (1e20 * (QDouble fromFloat:1.0)) asFloat |
1241 |
1241 |
1247 ! |
1247 ! |
1248 |
1248 |
1249 productFromQDouble:aQDouble |
1249 productFromQDouble:aQDouble |
1250 %{ |
1250 %{ |
1251 if (__Class(aQDouble) == QDouble) { |
1251 if (__Class(aQDouble) == QDouble) { |
1252 double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue; |
1252 double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue; |
1253 double *b = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue; |
1253 double *b = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue; |
1254 OBJ newQD; |
1254 OBJ newQD; |
1255 |
1255 |
1256 // sloppy |
1256 // sloppy |
1257 double p0, p1, p2, p3, p4, p5; |
1257 double p0, p1, p2, p3, p4, p5; |
1258 double q0, q1, q2, q3, q4, q5; |
1258 double q0, q1, q2, q3, q4, q5; |
1259 double t0, t1; |
1259 double t0, t1; |
1260 double s0, s1, s2; |
1260 double s0, s1, s2; |
1261 int savedCV; |
1261 int savedCV; |
1262 |
1262 |
1263 fpu_fix_start(&savedCV); |
1263 fpu_fix_start(&savedCV); |
1264 |
1264 |
1265 m_two_prod(p0, a[0], b[0], q0); |
1265 m_two_prod(p0, a[0], b[0], q0); |
1266 fprintf(stderr, "%f * %f -> %f, %f\n", a[0], b[0], p0, q0); |
1266 fprintf(stderr, "%f * %f -> %f, %f\n", a[0], b[0], p0, q0); |
1267 |
1267 |
1268 m_two_prod(p1, a[0], b[1], q1); |
1268 m_two_prod(p1, a[0], b[1], q1); |
1269 m_two_prod(p2, a[1], b[0], q2); |
1269 m_two_prod(p2, a[1], b[0], q2); |
1270 fprintf(stderr, "%f * %f -> %f, %f\n", a[0], b[1], p1, q1); |
1270 fprintf(stderr, "%f * %f -> %f, %f\n", a[0], b[1], p1, q1); |
1271 fprintf(stderr, "%f * %f -> %f, %f\n", a[1], b[0], p2, q2); |
1271 fprintf(stderr, "%f * %f -> %f, %f\n", a[1], b[0], p2, q2); |
1272 |
1272 |
1273 m_two_prod(p3, a[0], b[2], q3); |
1273 m_two_prod(p3, a[0], b[2], q3); |
1274 m_two_prod(p4, a[1], b[1], q4); |
1274 m_two_prod(p4, a[1], b[1], q4); |
1275 m_two_prod(p5, a[2], b[0], q5); |
1275 m_two_prod(p5, a[2], b[0], q5); |
1276 |
1276 |
1277 fprintf(stderr, "%f * %f -> %f, %f\n", a[0], b[2], p3, q3); |
1277 fprintf(stderr, "%f * %f -> %f, %f\n", a[0], b[2], p3, q3); |
1278 fprintf(stderr, "%f * %f -> %f, %f\n", a[1], b[1], p4, q4); |
1278 fprintf(stderr, "%f * %f -> %f, %f\n", a[1], b[1], p4, q4); |
1279 fprintf(stderr, "%f * %f -> %f, %f\n", a[2], b[0], p5, q5); |
1279 fprintf(stderr, "%f * %f -> %f, %f\n", a[2], b[0], p5, q5); |
1280 |
1280 |
1281 /* Start Accumulation */ |
1281 /* Start Accumulation */ |
1282 m_three_sum(p1, p2, q0); |
1282 m_three_sum(p1, p2, q0); |
1283 |
1283 |
1284 /* Six-Three Sum of p2, q1, q2, p3, p4, p5. */ |
1284 /* Six-Three Sum of p2, q1, q2, p3, p4, p5. */ |
1285 m_three_sum(p2, q1, q2); |
1285 m_three_sum(p2, q1, q2); |
1286 m_three_sum(p3, p4, p5); |
1286 m_three_sum(p3, p4, p5); |
1287 /* compute (s0, s1, s2) = (p2, q1, q2) + (p3, p4, p5). */ |
1287 /* compute (s0, s1, s2) = (p2, q1, q2) + (p3, p4, p5). */ |
1288 m_two_sum(s0, p2, p3, t0); |
1288 m_two_sum(s0, p2, p3, t0); |
1289 m_two_sum(s1, q1, p4, t1); |
1289 m_two_sum(s1, q1, p4, t1); |
1290 s2 = q2 + p5; |
1290 s2 = q2 + p5; |
1291 m_two_sum(s1, s1, t0, t0); |
1291 m_two_sum(s1, s1, t0, t0); |
1292 s2 += (t0 + t1); |
1292 s2 += (t0 + t1); |
1293 |
1293 |
1294 /* O(eps^3) order terms */ |
1294 /* O(eps^3) order terms */ |
1295 s1 += a[0]*b[3] + a[1]*b[2] + a[2]*b[1] + a[3]*b[0] + q0 + q3 + q4 + q5; |
1295 s1 += a[0]*b[3] + a[1]*b[2] + a[2]*b[1] + a[3]*b[0] + q0 + q3 + q4 + q5; |
1296 m_renorm5(p0, p1, s0, s1, s2); |
1296 m_renorm5(p0, p1, s0, s1, s2); |
1297 |
1297 |
1298 fpu_fix_end(&savedCV); |
1298 fpu_fix_end(&savedCV); |
1299 |
1299 |
1300 __qNew_qdReal(newQD, p0, p1, s0, s1); |
1300 __qNew_qdReal(newQD, p0, p1, s0, s1); |
1301 RETURN( newQD ); |
1301 RETURN( newQD ); |
1302 } |
1302 } |
1303 %}. |
1303 %}. |
1304 ^ super productFromQDouble:aQDouble. |
1304 ^ super productFromQDouble:aQDouble. |
1305 |
1305 |
1306 " |
1306 " |
1319 "Modified: / 14-06-2017 / 11:43:28 / cg" |
1319 "Modified: / 14-06-2017 / 11:43:28 / cg" |
1320 ! |
1320 ! |
1321 |
1321 |
1322 quotientFromQDouble:aQDouble |
1322 quotientFromQDouble:aQDouble |
1323 "sloppy" |
1323 "sloppy" |
1324 |
1324 |
1325 |q0 q1 q2 q3 r| |
1325 |q0 q1 q2 q3 r| |
1326 |
1326 |
1327 q0 := self d0 / aQDouble d0. |
1327 q0 := self d0 / aQDouble d0. |
1328 r := self - (aQDouble * q0). |
1328 r := self - (aQDouble * q0). |
1329 |
1329 |
1330 q1 := r d0 / aQDouble d0. |
1330 q1 := r d0 / aQDouble d0. |
1331 r := r - (aQDouble * q1). |
1331 r := r - (aQDouble * q1). |
1332 |
1332 |
1333 q2 := r d0 / aQDouble d0. |
1333 q2 := r d0 / aQDouble d0. |
1334 r := r - (aQDouble * q2). |
1334 r := r - (aQDouble * q2). |
1335 |
1335 |
1336 q3 := r d0 / aQDouble d0. |
1336 q3 := r d0 / aQDouble d0. |
1337 |
1337 |
1348 |
1348 |
1349 (QDouble fromFloat:2.0) / 2.0 |
1349 (QDouble fromFloat:2.0) / 2.0 |
1350 (QDouble fromFloat:1e20) / 2.0 |
1350 (QDouble fromFloat:1e20) / 2.0 |
1351 ((QDouble fromFloat:1.0) / 2.0) asFloat |
1351 ((QDouble fromFloat:1.0) / 2.0) asFloat |
1352 ((QDouble fromFloat:1e20 / 2.0)) asFloat |
1352 ((QDouble fromFloat:1e20 / 2.0)) asFloat |
1353 |
1353 |
1354 ((1e20 + (QDouble fromFloat:1.0) + 1e-20) / 2.0) asDoubleArray |
1354 ((1e20 + (QDouble fromFloat:1.0) + 1e-20) / 2.0) asDoubleArray |
1355 " |
1355 " |
1356 |
1356 |
1357 "Created: / 13-06-2017 / 17:50:35 / cg" |
1357 "Created: / 13-06-2017 / 17:50:35 / cg" |
1358 ! |
1358 ! |
1359 |
1359 |
1360 sumFromFloat:aFloat |
1360 sumFromFloat:aFloat |
1361 %{ |
1361 %{ |
1362 if (__isFloatLike(aFloat)) { |
1362 if (__isFloatLike(aFloat)) { |
1363 double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue; |
1363 double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue; |
1364 double b = __floatVal(aFloat); |
1364 double b = __floatVal(aFloat); |
1365 double c0, c1, c2, c3; |
1365 double c0, c1, c2, c3; |
1366 double e; |
1366 double e; |
1367 OBJ newQD; |
1367 OBJ newQD; |
1368 int savedCV; |
1368 int savedCV; |
1369 |
1369 |
1370 fpu_fix_start(&savedCV); |
1370 fpu_fix_start(&savedCV); |
1371 |
1371 |
1372 m_two_sum(c0, a[0], b, e); |
1372 m_two_sum(c0, a[0], b, e); |
1373 m_two_sum(c1 ,a[1], e, e); |
1373 m_two_sum(c1 ,a[1], e, e); |
1374 m_two_sum(c2, a[2], e, e); |
1374 m_two_sum(c2, a[2], e, e); |
1375 m_two_sum(c3, a[3], e, e); |
1375 m_two_sum(c3, a[3], e, e); |
1376 |
1376 |
1377 m_renorm5(c0, c1, c2, c3, e); |
1377 m_renorm5(c0, c1, c2, c3, e); |
1378 fpu_fix_end(&savedCV); |
1378 fpu_fix_end(&savedCV); |
1379 __qNew_qdReal(newQD, c0, c1, c2, c3); |
1379 __qNew_qdReal(newQD, c0, c1, c2, c3); |
1380 RETURN( newQD ); |
1380 RETURN( newQD ); |
1381 } |
1381 } |
1382 %}. |
1382 %}. |
1383 ^ super sumFromFloat:aFloat. |
1383 ^ super sumFromFloat:aFloat. |
1384 |
1384 |
1385 " |
1385 " |
1398 ! |
1398 ! |
1399 |
1399 |
1400 sumFromQDouble:aQDouble |
1400 sumFromQDouble:aQDouble |
1401 %{ |
1401 %{ |
1402 if (__Class(aQDouble) == QDouble) { |
1402 if (__Class(aQDouble) == QDouble) { |
1403 double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue; |
1403 double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue; |
1404 double *b = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue; |
1404 double *b = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue; |
1405 OBJ newQD; |
1405 OBJ newQD; |
1406 |
1406 |
1407 #ifndef QD_IEEE_ADD |
1407 #ifndef QD_IEEE_ADD |
1408 // sloppy_add... |
1408 // sloppy_add... |
1409 |
1409 |
1410 /* |
1410 /* |
1411 double s0, s1, s2, s3; |
1411 double s0, s1, s2, s3; |
1412 double t0, t1, t2, t3; |
1412 double t0, t1, t2, t3; |
1413 int savedCV; |
1413 int savedCV; |
1414 |
1414 |
1415 fpu_fix_start(&savedCV); |
1415 fpu_fix_start(&savedCV); |
1416 m_two_sum(s0, a[0], b[0], t0); |
1416 m_two_sum(s0, a[0], b[0], t0); |
1417 m_two_sum(s1, a[1], b[1], t1); |
1417 m_two_sum(s1, a[1], b[1], t1); |
1418 m_two_sum(s2, a[2], b[2], t2); |
1418 m_two_sum(s2, a[2], b[2], t2); |
1419 m_two_sum(s3, a[3], b[3], t3); |
1419 m_two_sum(s3, a[3], b[3], t3); |
1420 |
1420 |
1421 m_two_sum(s1, s1, t0, t0); |
1421 m_two_sum(s1, s1, t0, t0); |
1422 m_three_sum(s2, t0, t1); |
1422 m_three_sum(s2, t0, t1); |
1423 m_three_sum2(s3, t0, t2); |
1423 m_three_sum2(s3, t0, t2); |
1424 t0 = t0 + t1 + t3; |
1424 t0 = t0 + t1 + t3; |
1425 |
1425 |
1426 fpu_fix_end(&savedCV); |
1426 fpu_fix_end(&savedCV); |
1427 m_renorm5(s0, s1, s2, s3, t0); |
1427 m_renorm5(s0, s1, s2, s3, t0); |
1428 return qd_real(s0, s1, s2, s3, t0); |
1428 return qd_real(s0, s1, s2, s3, t0); |
1429 */ |
1429 */ |
1430 |
1430 |
1431 /* Same as above, but addition re-organized to minimize |
1431 /* Same as above, but addition re-organized to minimize |
1432 data dependency ... unfortunately some compilers are |
1432 data dependency ... unfortunately some compilers are |
1433 not very smart to do this automatically */ |
1433 not very smart to do this automatically */ |
1434 double s0, s1, s2, s3; |
1434 double s0, s1, s2, s3; |
1435 double t0, t1, t2, t3; |
1435 double t0, t1, t2, t3; |
1436 double v0, v1, v2, v3; |
1436 double v0, v1, v2, v3; |
1437 double u0, u1, u2, u3; |
1437 double u0, u1, u2, u3; |
1438 double w0, w1, w2, w3; |
1438 double w0, w1, w2, w3; |
1439 int savedCV; |
1439 int savedCV; |
1440 |
1440 |
1441 fpu_fix_start(&savedCV); |
1441 fpu_fix_start(&savedCV); |
1442 s0 = a[0] + b[0]; |
1442 s0 = a[0] + b[0]; |
1443 s1 = a[1] + b[1]; |
1443 s1 = a[1] + b[1]; |
1444 s2 = a[2] + b[2]; |
1444 s2 = a[2] + b[2]; |
1445 s3 = a[3] + b[3]; |
1445 s3 = a[3] + b[3]; |
1446 |
1446 |
1447 v0 = s0 - a[0]; |
1447 v0 = s0 - a[0]; |
1448 v1 = s1 - a[1]; |
1448 v1 = s1 - a[1]; |
1449 v2 = s2 - a[2]; |
1449 v2 = s2 - a[2]; |
1450 v3 = s3 - a[3]; |
1450 v3 = s3 - a[3]; |
1451 |
1451 |
1452 u0 = s0 - v0; |
1452 u0 = s0 - v0; |
1453 u1 = s1 - v1; |
1453 u1 = s1 - v1; |
1454 u2 = s2 - v2; |
1454 u2 = s2 - v2; |
1455 u3 = s3 - v3; |
1455 u3 = s3 - v3; |
1456 |
1456 |
1457 w0 = a[0] - u0; |
1457 w0 = a[0] - u0; |
1458 w1 = a[1] - u1; |
1458 w1 = a[1] - u1; |
1459 w2 = a[2] - u2; |
1459 w2 = a[2] - u2; |
1460 w3 = a[3] - u3; |
1460 w3 = a[3] - u3; |
1461 |
1461 |
1462 u0 = b[0] - v0; |
1462 u0 = b[0] - v0; |
1463 u1 = b[1] - v1; |
1463 u1 = b[1] - v1; |
1464 u2 = b[2] - v2; |
1464 u2 = b[2] - v2; |
1465 u3 = b[3] - v3; |
1465 u3 = b[3] - v3; |
1466 |
1466 |
1467 t0 = w0 + u0; |
1467 t0 = w0 + u0; |
1468 t1 = w1 + u1; |
1468 t1 = w1 + u1; |
1469 t2 = w2 + u2; |
1469 t2 = w2 + u2; |
1470 t3 = w3 + u3; |
1470 t3 = w3 + u3; |
1471 |
1471 |
1472 m_two_sum(s1, s1, t0, t0); |
1472 m_two_sum(s1, s1, t0, t0); |
1473 m_three_sum(s2, t0, t1); |
1473 m_three_sum(s2, t0, t1); |
1474 m_three_sum2(s3, t0, t2); |
1474 m_three_sum2(s3, t0, t2); |
1475 t0 = t0 + t1 + t3; |
1475 t0 = t0 + t1 + t3; |
1476 |
1476 |
1477 /* renormalize */ |
1477 /* renormalize */ |
1478 m_renorm5(s0, s1, s2, s3, t0); |
1478 m_renorm5(s0, s1, s2, s3, t0); |
1479 fpu_fix_end(&savedCV); |
1479 fpu_fix_end(&savedCV); |
1480 __qNew_qdReal(newQD, s0, s1, s2, s3); |
1480 __qNew_qdReal(newQD, s0, s1, s2, s3); |
1481 RETURN(newQD); |
1481 RETURN(newQD); |
1482 #else |
1482 #else |
1483 // ieee_add... |
1483 // ieee_add... |
1484 int i, j, k; |
1484 int i, j, k; |
1485 double s, t; |
1485 double s, t; |
1486 double u, v; /* double-length accumulator */ |
1486 double u, v; /* double-length accumulator */ |
1487 double x[4] = {0.0, 0.0, 0.0, 0.0}; |
1487 double x[4] = {0.0, 0.0, 0.0, 0.0}; |
1488 int savedCV; |
1488 int savedCV; |
1489 |
1489 |
1490 fpu_fix_start(&savedCV); |
1490 fpu_fix_start(&savedCV); |
1491 i = j = k = 0; |
1491 i = j = k = 0; |
1492 if (abs(a[i]) > abs(b[j])) |
1492 if (abs(a[i]) > abs(b[j])) |
1493 u = a[i++]; |
1493 u = a[i++]; |
1494 else |
1494 else |
1495 u = b[j++]; |
1495 u = b[j++]; |
1496 if (abs(a[i]) > abs(b[j])) |
1496 if (abs(a[i]) > abs(b[j])) |
1497 v = a[i++]; |
1497 v = a[i++]; |
1498 else |
1498 else |
1499 v = b[j++]; |
1499 v = b[j++]; |
1500 |
1500 |
1501 u = quick_two_sum(u, v, v); |
1501 u = quick_two_sum(u, v, v); |
1502 |
1502 |
1503 while (k < 4) { |
1503 while (k < 4) { |
1504 if (i >= 4 && j >= 4) { |
1504 if (i >= 4 && j >= 4) { |
1505 x[k] = u; |
1505 x[k] = u; |
1506 if (k < 3) |
1506 if (k < 3) |
1507 x[++k] = v; |
1507 x[++k] = v; |
1508 break; |
1508 break; |
1509 } |
1509 } |
1510 |
1510 |
1511 if (i >= 4) |
1511 if (i >= 4) |
1512 t = b[j++]; |
1512 t = b[j++]; |
1513 else if (j >= 4) |
1513 else if (j >= 4) |
1514 t = a[i++]; |
1514 t = a[i++]; |
1515 else if (abs(a[i]) > abs(b[j])) { |
1515 else if (abs(a[i]) > abs(b[j])) { |
1516 t = a[i++]; |
1516 t = a[i++]; |
1517 } else |
1517 } else |
1518 t = b[j++]; |
1518 t = b[j++]; |
1519 |
1519 |
1520 s = quick_three_accum(u, v, t); |
1520 s = quick_three_accum(u, v, t); |
1521 |
1521 |
1522 if (s != 0.0) { |
1522 if (s != 0.0) { |
1523 x[k++] = s; |
1523 x[k++] = s; |
1524 } |
1524 } |
1525 } |
1525 } |
1526 |
1526 |
1527 /* add the rest. */ |
1527 /* add the rest. */ |
1528 for (k = i; k < 4; k++) |
1528 for (k = i; k < 4; k++) |
1529 x[3] += a[k]; |
1529 x[3] += a[k]; |
1530 for (k = j; k < 4; k++) |
1530 for (k = j; k < 4; k++) |
1531 x[3] += b[k]; |
1531 x[3] += b[k]; |
1532 |
1532 |
1533 m_renorm4(x[0], x[1], x[2], x[3]); |
1533 m_renorm4(x[0], x[1], x[2], x[3]); |
1534 fpu_fix_end(&savedCV); |
1534 fpu_fix_end(&savedCV); |
1535 __qNew_qdReal(newQD, x[0], x[1], x[2], x[3]); |
1535 __qNew_qdReal(newQD, x[0], x[1], x[2], x[3]); |
1536 RETURN(newQD); |
1536 RETURN(newQD); |
1537 #endif |
1537 #endif |
1538 } |
1538 } |
1539 %}. |
1539 %}. |
1540 ^ super sumFromQDouble:aQDouble |
1540 ^ super sumFromQDouble:aQDouble |
1541 |
1541 |
1542 " |
1542 " |
1543 (QDouble fromFloat:1.0) + (QDouble fromFloat:1.0) |
1543 (QDouble fromFloat:1.0) + (QDouble fromFloat:1.0) |
1544 (QDouble fromFloat:1.0) + 1.0 |
1544 (QDouble fromFloat:1.0) + 1.0 |
1545 1.0 + (QDouble fromFloat:1.0) |
1545 1.0 + (QDouble fromFloat:1.0) |
1546 |
1546 |
1559 |
1559 |
1560 inspectorExtraAttributes |
1560 inspectorExtraAttributes |
1561 "extra (pseudo instvar) entries to be shown in an inspector." |
1561 "extra (pseudo instvar) entries to be shown in an inspector." |
1562 |
1562 |
1563 ^ super inspectorExtraAttributes |
1563 ^ super inspectorExtraAttributes |
1564 add:'-{doubles}' -> |
1564 add:'-{doubles}' -> |
1565 [ |
1565 [ |
1566 self asDoubleArray printString |
1566 self asDoubleArray printString |
1567 ]; |
1567 ]; |
1568 yourself |
1568 yourself |
1569 |
1569 |
1570 "Created: / 12-06-2017 / 23:43:05 / cg" |
1570 "Created: / 12-06-2017 / 23:43:05 / cg" |
1571 ! ! |
1571 ! ! |
1572 |
1572 |
1573 !QDouble methodsFor:'mathematical functions'! |
1573 !QDouble methodsFor:'mathematical functions'! |
1582 double x0, x1, x2, x3; |
1582 double x0, x1, x2, x3; |
1583 x1 = x2 = x3 = 0.0; |
1583 x1 = x2 = x3 = 0.0; |
1584 x0 =floor(a[0]); |
1584 x0 =floor(a[0]); |
1585 |
1585 |
1586 if (x0 == a[0]) { |
1586 if (x0 == a[0]) { |
1587 x1 = floor(a[1]); |
1587 x1 = floor(a[1]); |
1588 |
1588 |
1589 if (x1 == a[1]) { |
1589 if (x1 == a[1]) { |
1590 x2 = floor(a[2]); |
1590 x2 = floor(a[2]); |
1591 |
1591 |
1592 if (x2 == a[2]) { |
1592 if (x2 == a[2]) { |
1593 x3 = floor(a[3]); |
1593 x3 = floor(a[3]); |
1594 } |
1594 } |
1595 } |
1595 } |
1596 |
1596 |
1597 m_renorm4(x0, x1, x2, x3); |
1597 m_renorm4(x0, x1, x2, x3); |
1598 __qNew_qdReal(newQD, x0, x1, x2, x3); |
1598 __qNew_qdReal(newQD, x0, x1, x2, x3); |
1599 RETURN( newQD ); |
1599 RETURN( newQD ); |
1600 } |
1600 } |
1601 |
1601 |
1602 __qNew_qdReal(newQD, x0, x1, x2, x3); |
1602 __qNew_qdReal(newQD, x0, x1, x2, x3); |
1603 RETURN( newQD ); |
1603 RETURN( newQD ); |
1604 %}. |
1604 %}. |
1606 " |
1606 " |
1607 (QDouble fromFloat:4.0) floor |
1607 (QDouble fromFloat:4.0) floor |
1608 (QDouble fromFloat:4.1) floor |
1608 (QDouble fromFloat:4.1) floor |
1609 (QDouble fromFloat:0.1) floor |
1609 (QDouble fromFloat:0.1) floor |
1610 (0.1 + (QDouble fromFloat:1.0)) floor |
1610 (0.1 + (QDouble fromFloat:1.0)) floor |
1611 (1e20 + (QDouble fromFloat:1.0)) floor |
1611 (1e20 + (QDouble fromFloat:1.0)) floor |
1612 |
1612 |
1613 (QDouble fromFloat:1.5) floor |
1613 (QDouble fromFloat:1.5) floor |
1614 (QDouble fromFloat:0.5) floor |
1614 (QDouble fromFloat:0.5) floor |
1615 (QDouble fromFloat:-0.5) floor |
1615 (QDouble fromFloat:-0.5) floor |
1616 (QDouble fromFloat:-1.5) floor |
1616 (QDouble fromFloat:-1.5) floor |
1619 "Created: / 13-06-2017 / 01:52:44 / cg" |
1619 "Created: / 13-06-2017 / 01:52:44 / cg" |
1620 "Modified (comment): / 13-06-2017 / 17:33:19 / cg" |
1620 "Modified (comment): / 13-06-2017 / 17:33:19 / cg" |
1621 ! |
1621 ! |
1622 |
1622 |
1623 negated |
1623 negated |
1624 ^ self class |
1624 ^ self class |
1625 d0:(self d0) negated |
1625 d0:(self d0) negated |
1626 d1:(self d1) negated |
1626 d1:(self d1) negated |
1627 d2:(self d2) negated |
1627 d2:(self d2) negated |
1628 d3:(self d3) negated |
1628 d3:(self d3) negated |
1629 |
1629 |
1630 " |
1630 " |
1631 (QDouble fromFloat:1.0) negated |
1631 (QDouble fromFloat:1.0) negated |
1632 ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) negated asDoubleArray |
1632 ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) negated asDoubleArray |
1633 |
1633 |
1634 (((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) |
1634 (((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) |
1635 + ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0))) asDoubleArray |
1635 + ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0))) asDoubleArray |
1646 double q0, q1, q2, q3; |
1646 double q0, q1, q2, q3; |
1647 double s0, s1; |
1647 double s0, s1; |
1648 double t0, t1; |
1648 double t0, t1; |
1649 double t; |
1649 double t; |
1650 OBJ newQD; |
1650 OBJ newQD; |
1651 |
1651 |
1652 m_two_sqr(p0, a[0], q0); |
1652 m_two_sqr(p0, a[0], q0); |
1653 t = 2.0 * a[0]; |
1653 t = 2.0 * a[0]; |
1654 |
1654 |
1655 m_two_prod(p1, t, a[1], q1); |
1655 m_two_prod(p1, t, a[1], q1); |
1656 m_two_prod(p2, t, a[2], q2); |
1656 m_two_prod(p2, t, a[2], q2); |
1689 RETURN( newQD ); |
1689 RETURN( newQD ); |
1690 %}. |
1690 %}. |
1691 |
1691 |
1692 " |
1692 " |
1693 (QDouble fromFloat:4.0) squared |
1693 (QDouble fromFloat:4.0) squared |
1694 (1e20 + (QDouble fromFloat:1.0)) squared |
1694 (1e20 + (QDouble fromFloat:1.0)) squared |
1695 " |
1695 " |
1696 |
1696 |
1697 "Created: / 13-06-2017 / 01:27:58 / cg" |
1697 "Created: / 13-06-2017 / 01:27:58 / cg" |
1698 ! ! |
1698 ! ! |
1699 |
1699 |
1703 |numDigits r e i d| |
1703 |numDigits r e i d| |
1704 |
1704 |
1705 numDigits := precision+1. "/ number of digits |
1705 numDigits := precision+1. "/ number of digits |
1706 r := self abs. |
1706 r := self abs. |
1707 self d0 = 0.0 ifTrue:[ |
1707 self d0 = 0.0 ifTrue:[ |
1708 expn value:0. |
1708 expn value:0. |
1709 precision timesRepeat:[ outStream nextPut:$0 ]. |
1709 precision timesRepeat:[ outStream nextPut:$0 ]. |
1710 ^ self. |
1710 ^ self. |
1711 ]. |
1711 ]. |
1712 |
1712 |
1713 "/ determine approx. exponent |
1713 "/ determine approx. exponent |
1714 e := self d0 abs log10 floor. |
1714 e := self d0 abs log10 floor. |
1715 self halt. |
1715 self halt. |
1716 e < -300 ifTrue:[ |
1716 e < -300 ifTrue:[ |
1717 r := r * (10.0 raisedToInteger:300). |
1717 r := r * (10.0 raisedToInteger:300). |
1718 r := r / (10.0 raisedToInteger:(e+300)). |
1718 r := r / (10.0 raisedToInteger:(e+300)). |
1719 ] ifFalse:[ |
1719 ] ifFalse:[ |
1720 e > 300 ifTrue:[ |
1720 e > 300 ifTrue:[ |
1721 ] ifFalse:[ |
1721 ] ifFalse:[ |
1722 ] |
1722 ] |
1723 ]. |
1723 ]. |
1724 |
1724 |
1725 |
1725 |
1726 " |
1726 " |
1727 1.2345 asQDouble printDigitsOn:Transcript precision:5 exponentInto:[:e |] |
1727 1.2345 asQDouble printDigitsOn:Transcript precision:5 exponentInto:[:e |] |
1728 " |
1728 " |
1729 |
1729 |
1730 "Created: / 13-06-2017 / 17:28:08 / cg" |
1730 "Created: / 13-06-2017 / 17:28:08 / cg" |
1732 |
1732 |
1733 printString |
1733 printString |
1734 "return a printed representation of the receiver" |
1734 "return a printed representation of the receiver" |
1735 |
1735 |
1736 self d1 = 0.0 ifTrue:[ |
1736 self d1 = 0.0 ifTrue:[ |
1737 ^ self d0 printString |
1737 ^ self d0 printString |
1738 ]. |
1738 ]. |
1739 ^ self d0 printString , '...' |
1739 ^ self d0 printString , '...' |
1740 |
1740 |
1741 "Created: / 12-06-2017 / 23:41:04 / cg" |
1741 "Created: / 12-06-2017 / 23:41:04 / cg" |
1742 ! ! |
1742 ! ! |
1744 !QDouble methodsFor:'private accessing'! |
1744 !QDouble methodsFor:'private accessing'! |
1745 |
1745 |
1746 d0 |
1746 d0 |
1747 "the most significant (and highest valued) 53 bits of precision" |
1747 "the most significant (and highest valued) 53 bits of precision" |
1748 %{ |
1748 %{ |
1749 RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[0]) ); |
1749 RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[0]) ); |
1750 %} |
1750 %} |
1751 |
1751 |
1752 "Created: / 12-06-2017 / 20:15:12 / cg" |
1752 "Created: / 12-06-2017 / 20:15:12 / cg" |
1753 "Modified (comment): / 13-06-2017 / 17:59:47 / cg" |
1753 "Modified (comment): / 13-06-2017 / 17:59:47 / cg" |
1754 ! |
1754 ! |
1755 |
1755 |
1756 d1 |
1756 d1 |
1757 "the next most significant (and next highest valued) 53 bits of precision" |
1757 "the next most significant (and next highest valued) 53 bits of precision" |
1758 %{ |
1758 %{ |
1759 RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[1]) ); |
1759 RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[1]) ); |
1760 %} |
1760 %} |
1761 |
1761 |
1762 "Created: / 12-06-2017 / 20:15:12 / cg" |
1762 "Created: / 12-06-2017 / 20:15:12 / cg" |
1763 "Modified (comment): / 13-06-2017 / 18:00:00 / cg" |
1763 "Modified (comment): / 13-06-2017 / 18:00:00 / cg" |
1764 ! |
1764 ! |
1765 |
1765 |
1766 d2 |
1766 d2 |
1767 %{ |
1767 %{ |
1768 RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[2]) ); |
1768 RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[2]) ); |
1769 %} |
1769 %} |
1770 |
1770 |
1771 "Created: / 12-06-2017 / 20:15:29 / cg" |
1771 "Created: / 12-06-2017 / 20:15:29 / cg" |
1772 ! |
1772 ! |
1773 |
1773 |
1774 d3 |
1774 d3 |
1775 "the least significant (and smallest valued) 53 bits of precision" |
1775 "the least significant (and smallest valued) 53 bits of precision" |
1776 %{ |
1776 %{ |
1777 RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[3]) ); |
1777 RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[3]) ); |
1778 %} |
1778 %} |
1779 |
1779 |
1780 "Created: / 12-06-2017 / 20:15:32 / cg" |
1780 "Created: / 12-06-2017 / 20:15:32 / cg" |
1781 "Modified (comment): / 13-06-2017 / 18:00:18 / cg" |
1781 "Modified (comment): / 13-06-2017 / 18:00:18 / cg" |
1782 ! |
1782 ! |
1783 |
1783 |
1784 renorm |
1784 renorm |
1785 %{ |
1785 %{ |
1786 double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue; |
1786 double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue; |
1787 double c0, c1, c2, c3; |
1787 double c0, c1, c2, c3; |
1788 OBJ newQD; |
1788 OBJ newQD; |
1789 |
1789 |
1790 c0 = a[0]; |
1790 c0 = a[0]; |
1791 c1 = a[1]; |
1791 c1 = a[1]; |
1814 ! |
1814 ! |
1815 |
1815 |
1816 version_CVS |
1816 version_CVS |
1817 ^ '$Header$' |
1817 ^ '$Header$' |
1818 ! ! |
1818 ! ! |
1819 |