00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include "quad.h"
00047 #include "stdio.h"
00048 #include "stdlib.h"
00049 #include "math.h"
00050 #include <fp_class.h>
00051 #include "defs.h"
00052 #include "quadsim.h"
00053
00054
00055
00056 #define DMANTWIDTH 52
00057 #define DEXPWIDTH 11
00058 #define DSIGNMASK 0x7fffffffffffffffll
00059 #define DEXPMASK 0x800fffffffffffffll
00060 #define DQNANBITMASK 0xfff7ffffffffffffll
00061
00062 #define MANTWIDTH 23
00063 #define EXPWIDTH 8
00064 #define SIGNMASK 0x7fffffff
00065 #define EXPMASK 0x807fffff
00066 #define QNANBITMASK 0xffbfffff
00067
00068 typedef union
00069 {
00070 struct
00071 {
00072 UINT32 hi;
00073 UINT32 lo;
00074 } word;
00075
00076 double d;
00077 } du;
00078
00079 static const du m_twop31 =
00080 {0xc1e00000, 0x00000000};
00081
00082 static const du twop31m1 =
00083 {0x41dfffff, 0xffc00000};
00084
00085 static const du twop32m1 =
00086 {0x41efffff, 0xffe00000};
00087
00088 static const du twop52 =
00089 {0x43300000, 0x00000000};
00090
00091 static const du twop62 =
00092 {0x43d00000, 0x00000000};
00093
00094 static const du m_twop63 =
00095 {0xc3e00000, 0x00000000};
00096
00097 static const du twop63 =
00098 {0x43e00000, 0x00000000};
00099
00100 static const du twop64 =
00101 {0x43f00000, 0x00000000};
00102
00103 static const du twopm916 =
00104 {0x06b00000, 0x00000000};
00105
00106
00107 static const du myinfinity =
00108 {0x7ff00000, 0x00000000};
00109
00110 extern INT c_q_le(QUAD x, QUAD y, INT *p_err );
00111 extern INT c_q_ge(QUAD x, QUAD y, INT *p_err );
00112 extern INT32 c_ji_qint(QUAD x, INT *p_err );
00113 extern INT32 c_fp_class_q(QUAD x);
00114 extern UINT32 c_ji_quint(QUAD x, INT *p_err );
00115 extern INT64 c_ki_qint(QUAD x, INT *p_err );
00116 extern UINT64 c_ki_quint(QUAD x, INT *p_err );
00117 extern float c_sngl_q(QUAD x, INT *p_err );
00118 extern double c_dble_q(QUAD x, INT *p_err );
00119 extern QUAD c_q_flotj(INT32 n, INT *p_err );
00120 extern QUAD c_q_flotju(UINT32 n, INT *p_err );
00121 extern QUAD c_q_flotk(INT64 n, INT *p_err );
00122 extern QUAD c_q_flotku(UINT64 n, INT *p_err );
00123 extern QUAD c_q_ext( float x, INT *p_err );
00124 extern QUAD c_q_extd(double x, INT *p_err );
00125 extern QUAD c_q_trunc(QUAD x, INT *p_err );
00126 extern double trunc(double x);
00127
00128 #if defined(_GCC_NO_PRAGMAWEAK) || defined(__CYGWIN__)
00129
00130 #define c_q_trunc __c_q_trunc
00131 #define c_q_ge __c_q_ge
00132 #define c_ki_qint __c_ki_qint
00133 #define c_q_le __c_q_le
00134
00135 #endif
00136
00137
00138
00139 #pragma weak c_ji_qint = __c_ji_qint
00140 #define c_ji_qint __c_ji_qint
00141
00142 INT32
00143 c_ji_qint(QUAD x, INT *p_err )
00144 {
00145 QUAD xi;
00146 INT32 result;
00147
00148 *p_err = 0;
00149
00150 if ( x.hi != x.hi )
00151 {
00152 *p_err = 1;
00153
00154 return ( (INT32)x.hi );
00155 }
00156
00157 if ( fabs(x.hi) == myinfinity.d )
00158 {
00159 *p_err = 1;
00160
00161 return ( (INT32)x.hi );
00162 }
00163
00164 xi = c_q_trunc(x, p_err);
00165
00166 if ( xi.hi > twop31m1.d )
00167 *p_err = 1;
00168
00169 if ( xi.hi < m_twop31.d )
00170 *p_err = 1;
00171
00172 result = (INT32)xi.hi;
00173
00174 return ( result );
00175 }
00176
00177
00178
00179 #pragma weak c_ji_quint = __c_ji_quint
00180 #define c_ji_quint __c_ji_quint
00181
00182 UINT32
00183 c_ji_quint(QUAD x, INT *p_err )
00184 {
00185 QUAD xi;
00186 INT64 n;
00187 UINT32 result;
00188
00189 *p_err = 0;
00190
00191 if ( x.hi != x.hi )
00192 {
00193 *p_err = 1;
00194
00195 return ( (UINT32)x.hi );
00196 }
00197
00198 if ( fabs(x.hi) == myinfinity.d )
00199 {
00200 *p_err = 1;
00201
00202 return ( (UINT32)x.hi );
00203 }
00204
00205 xi = c_q_trunc(x, p_err);
00206
00207 if ( xi.hi > twop32m1.d )
00208 {
00209 *p_err = 1;
00210
00211 return ( (UINT32)x.hi );
00212 }
00213
00214 if ( xi.hi < 0.0 )
00215 {
00216 *p_err = 1;
00217
00218 return ( (UINT32)x.hi );
00219 }
00220
00221 n = c_ki_qint(xi, p_err);
00222
00223 result = n & 0xffffffff;
00224
00225 return ( result );
00226 }
00227
00228
00229
00230 #pragma weak c_ki_qint = __c_ki_qint
00231 #define c_ki_qint __c_ki_qint
00232
00233 INT64
00234 c_ki_qint(QUAD x, INT *p_err )
00235 {
00236 QUAD xi;
00237 INT64 t;
00238
00239 *p_err = 0;
00240
00241 if ( x.hi != x.hi )
00242 {
00243 *p_err = 1;
00244
00245 return ( (INT64)x.hi );
00246 }
00247
00248 if ( fabs(x.hi) == myinfinity.d )
00249 {
00250 *p_err = 1;
00251
00252 return ( (INT64)x.hi );
00253 }
00254
00255 xi = c_q_trunc(x, p_err);
00256
00257 if ( (xi.hi > twop63.d) ||
00258 ((xi.hi == twop63.d) && (xi.lo >= 0.0))
00259 )
00260 {
00261
00262
00263 *p_err = 1;
00264
00265 return ( (INT64)xi.hi );
00266 }
00267
00268 if ( (xi.hi < m_twop63.d) ||
00269 ((xi.hi == m_twop63.d) && (xi.lo < 0.0))
00270 )
00271 {
00272
00273
00274 if ( xi.hi == m_twop63.d )
00275 {
00276 xi.hi *= 2.0;
00277 }
00278
00279 *p_err = 1;
00280
00281 return ( (INT64)xi.hi );
00282 }
00283
00284 if ( fabs(xi.hi) > twop62.d )
00285 {
00286
00287
00288 t = 0.5*xi.hi;
00289 return ( ((INT64)xi.lo) + t + t );
00290 }
00291
00292
00293
00294 return ( (INT64)xi.hi + (INT64)xi.lo );
00295 }
00296
00297
00298
00299 #pragma weak c_ki_quint = __c_ki_quint
00300 #define c_ki_quint __c_ki_quint
00301
00302 UINT64
00303 c_ki_quint(QUAD x, INT *p_err )
00304 {
00305 QUAD xi;
00306 double z;
00307 UINT64 t;
00308
00309 *p_err = 0;
00310
00311 if ( x.hi != x.hi )
00312 {
00313 *p_err = 1;
00314
00315 return ( (UINT64)x.hi );
00316 }
00317
00318 if ( fabs(x.hi) == myinfinity.d )
00319 {
00320 *p_err = 1;
00321
00322 return ( (UINT64)x.hi );
00323 }
00324
00325 xi = c_q_trunc(x, p_err);
00326
00327 if ( (xi.hi > twop64.d) ||
00328 ((xi.hi == twop64.d) && (xi.lo > -1.0))
00329 )
00330 {
00331 *p_err = 1;
00332
00333 return ( (UINT64)x.hi );
00334 }
00335
00336 if ( xi.hi < 0.0 )
00337 {
00338 *p_err = 1;
00339
00340 return ( (UINT64)x.hi );
00341 }
00342
00343 if ( (xi.hi > twop63.d) ||
00344 (xi.hi == twop63.d) && (xi.lo >= 0.0)
00345 )
00346 {
00347
00348
00349 z = xi.hi - twop64.d;
00350
00351
00352
00353 xi.hi = z + xi.lo;
00354 xi.lo = z - xi.hi + xi.lo;
00355 }
00356
00357 if ( fabs(xi.hi) > twop62.d )
00358 {
00359
00360
00361 t = 0.5*xi.hi;
00362 return ( ((UINT64)xi.lo) + t + t );
00363 }
00364
00365
00366
00367 return ( (UINT64)xi.hi + (UINT64)xi.lo );
00368 }
00369
00370
00371
00372 #pragma weak c_sngl_q = __c_sngl_q
00373 #define c_sngl_q __c_sngl_q
00374
00375 float
00376 c_sngl_q(QUAD x, INT *p_err )
00377 {
00378 *p_err = 0;
00379
00380 return ( (float)x.hi );
00381 }
00382
00383
00384
00385 #pragma weak c_dble_q = __c_dble_q
00386 #define c_dble_q __c_dble_q
00387
00388 double
00389 c_dble_q(QUAD x, INT *p_err )
00390 {
00391 *p_err = 0;
00392
00393 return ( x.hi );
00394 }
00395
00396
00397
00398 #pragma weak c_q_flotj = __c_q_flotj
00399 #define c_q_flotj __c_q_flotj
00400
00401 QUAD
00402 c_q_flotj(INT32 n, INT *p_err )
00403 {
00404 QUAD result;
00405
00406 *p_err = 0;
00407
00408 result.hi = n;
00409 result.lo = 0.0;
00410 return ( result );
00411 }
00412
00413
00414
00415 #pragma weak c_q_flotju = __c_q_flotju
00416 #define c_q_flotju __c_q_flotju
00417
00418 QUAD
00419 c_q_flotju(UINT32 n, INT *p_err )
00420 {
00421 QUAD result;
00422
00423 *p_err = 0;
00424
00425 result.hi = n;
00426 result.lo = 0.0;
00427 return ( result );
00428 }
00429
00430
00431
00432 #pragma weak c_q_flotk = __c_q_flotk
00433 #define c_q_flotk __c_q_flotk
00434
00435 QUAD
00436 c_q_flotk(INT64 n, INT *p_err )
00437 {
00438 INT64 m;
00439 double w, ww;
00440 QUAD result;
00441
00442 *p_err = 0;
00443
00444 m = (n >> 11);
00445 m <<= 11;
00446
00447 w = m;
00448
00449 ww = n - m;
00450
00451
00452
00453 result.hi = w + ww;
00454 result.lo = w - result.hi + ww;
00455
00456 return ( result );
00457 }
00458
00459
00460
00461 #pragma weak c_q_flotku = __c_q_flotku
00462 #define c_q_flotku __c_q_flotku
00463
00464 QUAD
00465 c_q_flotku(UINT64 n, INT *p_err )
00466 {
00467 UINT64 m;
00468 double w, ww;
00469 QUAD result;
00470
00471 *p_err = 0;
00472
00473 m = (n >> 11);
00474 m <<= 11;
00475
00476 w = m;
00477
00478 ww = n - m;
00479
00480
00481
00482 result.hi = w + ww;
00483 result.lo = w - result.hi + ww;
00484
00485 return ( result );
00486 }
00487
00488
00489
00490 #pragma weak c_q_ext = __c_q_ext
00491 #define c_q_ext __c_q_ext
00492
00493 QUAD
00494 c_q_ext( float x, INT *p_err )
00495 {
00496 QUAD result;
00497
00498 *p_err = 0;
00499
00500 result.hi = x;
00501 result.lo = 0.0;
00502 return ( result );
00503 }
00504
00505
00506
00507 #pragma weak c_q_extd = __c_q_extd
00508 #define c_q_extd __c_q_extd
00509
00510 QUAD
00511 c_q_extd(double x, INT *p_err )
00512 {
00513 QUAD result;
00514
00515 *p_err = 0;
00516
00517 result.hi = x;
00518 result.lo = 0.0;
00519 return ( result );
00520 }
00521
00522
00523
00524
00525
00526 #pragma weak c_q_trunc = __c_q_trunc
00527 #define c_q_trunc __c_q_trunc
00528
00529 QUAD
00530 c_q_trunc(QUAD x, INT *p_err )
00531 {
00532 double uhi, ulo;
00533 QUAD result;
00534
00535 uhi = x.hi;
00536 ulo = x.lo;
00537
00538 *p_err = 0;
00539
00540 if ( uhi != uhi )
00541 {
00542 result.hi = uhi;
00543 result.lo = ulo;
00544
00545 return ( result );
00546 }
00547
00548 if ( uhi >= 0.0 )
00549 {
00550 if ( uhi < twop52.d )
00551 {
00552
00553
00554
00555 result.hi = trunc(uhi);
00556
00557 result.lo = 0.0;
00558
00559 if ( result.hi < uhi )
00560 return ( result );
00561
00562
00563
00564 if ( ulo < 0.0 )
00565 {
00566 result.hi -= 1.0;
00567
00568 return ( result );
00569 }
00570
00571 return ( result );
00572 }
00573 else if ( fabs(ulo) < twop52.d )
00574 {
00575
00576
00577
00578 result.hi = uhi;
00579
00580 result.lo = trunc(ulo);
00581
00582 if ( result.lo > ulo )
00583 {
00584 result.lo -= 1.0;
00585 }
00586
00587 return ( result );
00588 }
00589
00590
00591
00592 result.hi = uhi;
00593 result.lo = ulo;
00594
00595 return ( result );
00596 }
00597 else
00598 {
00599 if ( fabs(uhi) < twop52.d )
00600 {
00601
00602
00603
00604 result.hi = trunc(uhi);
00605
00606 result.lo = 0.0;
00607
00608 if ( result.hi > uhi )
00609 return ( result );
00610
00611
00612
00613 if ( ulo > 0.0 )
00614 {
00615 result.hi += 1.0;
00616
00617 return ( result );
00618 }
00619
00620 return ( result );
00621 }
00622 else if ( fabs(ulo) < twop52.d )
00623 {
00624
00625
00626
00627 result.hi = uhi;
00628
00629 result.lo = trunc(ulo);
00630
00631 if ( result.lo < ulo )
00632 {
00633 result.lo += 1.0;
00634 }
00635
00636 return ( result );
00637 }
00638
00639
00640
00641 result.hi = uhi;
00642 result.lo = ulo;
00643
00644 return ( result );
00645 }
00646 }
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660 #pragma weak c_fp_class_q = __c_fp_class_q
00661 #define c_fp_class_q __c_fp_class_q
00662
00663 INT
00664 fp_class_d( double x )
00665 {
00666 UINT64 ll, exp, mantissa;
00667 INT32 sign;
00668
00669 ll = *(UINT64*)&x;
00670 exp = (ll >> DMANTWIDTH);
00671 sign = (exp >> DEXPWIDTH);
00672 exp &= 0x7ff;
00673 mantissa = (ll & (DSIGNMASK & DEXPMASK));
00674 if ( exp == 0x7ff ) {
00675
00676 if ( mantissa == 0 )
00677 return ( (sign == 0) ? FP_POS_INF : FP_NEG_INF );
00678 else if ( mantissa & ~DQNANBITMASK )
00679 return ( FP_QNAN );
00680 else
00681 return ( FP_SNAN );
00682 }
00683
00684 if ( exp == 0 ) {
00685 if ( mantissa == 0 )
00686 return ( (sign == 0) ? FP_POS_ZERO : FP_NEG_ZERO );
00687 else
00688 return ( (sign == 0) ? FP_POS_DENORM : FP_NEG_DENORM );
00689 }
00690 else
00691 return ( (sign == 0) ? FP_POS_NORM : FP_NEG_NORM );
00692 }
00693
00694 INT32
00695 c_fp_class_q(QUAD x)
00696 {
00697 QUAD y;
00698 INT err;
00699 INT32 class;
00700
00701
00702
00703
00704
00705
00706 class = fp_class_d(x.hi);
00707
00708 if ( (class != FP_POS_NORM) && (class != FP_NEG_NORM) )
00709 return ( class );
00710
00711 class = fp_class_d(x.lo);
00712
00713 if ( (class == FP_POS_DENORM) && (class == FP_NEG_DENORM) )
00714 return ( class );
00715
00716 y.hi = twopm916.d;
00717 y.lo = 0.0;
00718
00719 if ( c_q_ge(x, y, &err) )
00720 return ( FP_POS_NORM );
00721
00722 y.hi = -y.hi;
00723
00724 if ( c_q_le(x, y, &err) )
00725 return ( FP_POS_NORM );
00726
00727 if ( x.hi > 0.0 )
00728 return ( FP_POS_DENORM );
00729
00730 return ( FP_NEG_DENORM );
00731 }
00732