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