1 /****************************************************************************** 2 Copyright (c) 2007-2011, Intel Corp. 3 All rights reserved. 4 5 Redistribution and use in source and binary forms, with or without 6 modification, are permitted provided that the following conditions are met: 7 8 * Redistributions of source code must retain the above copyright notice, 9 this list of conditions and the following disclaimer. 10 * Redistributions in binary form must reproduce the above copyright 11 notice, this list of conditions and the following disclaimer in the 12 documentation and/or other materials provided with the distribution. 13 * Neither the name of Intel Corporation nor the names of its contributors 14 may be used to endorse or promote products derived from this software 15 without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 THE POSSIBILITY OF SUCH DAMAGE. 28 ******************************************************************************/ 29 30 #if !defined(DPML_UX_H) 31 #define DPML_UX_H 32 33 #if !defined(X_FLOAT) 34 # define X_FLOAT 35 #endif 36 #define NEW_DPML_MACROS 1 37 #define DPML_PROTOTYPES_H 38 39 #include "dpml_private.h" 40 41 /* Alignment macros for 16-byte floating point types _Quad and _Decimal128. */ 42 #if defined(_WIN32)||defined(_WIN64) 43 #define F128_ALIGN_16 __declspec(align(16)) 44 #else 45 #if !defined(HPUX_OS) 46 #define F128_ALIGN_16 __attribute__((aligned(16))) 47 #else 48 #define F128_ALIGN_16 49 #endif 50 #endif 51 52 /* 53 ** Types: 54 ** 55 ** Define the basic data types that are used by the unpacked x_float routines 56 ** as well as macros to access their fields and define specific values 57 */ 58 59 typedef INT_32 UX_SIGN_TYPE; 60 typedef INT_32 UX_EXPONENT_TYPE; 61 typedef U_INT_32 UX_UNSIGNED_EXPONENT_TYPE; 62 typedef U_WORD UX_FRACTION_DIGIT_TYPE; 63 typedef WORD UX_SIGNED_FRACTION_DIGIT_TYPE; 64 65 #define BITS_PER_UX_SIGN_TYPE 32 66 #define BITS_PER_UX_EXPONENT_TYPE 32 67 #define BITS_PER_UX_FRACTION_DIGIT_TYPE BITS_PER_WORD 68 69 #define NUM_UX_FRACTION_DIGITS (128/BITS_PER_UX_FRACTION_DIGIT_TYPE) 70 #define NUM_X_FRACTION_DIGITS (128/BITS_PER_UX_FRACTION_DIGIT_TYPE) 71 72 #if (VAX_FLOATING) || (ENDIANESS == big_endian) 73 # define DIGIT(n) digit[n] 74 #else 75 # define DIGIT(n) digit[NUM_UX_FRACTION_DIGITS - 1 - (n)] 76 #endif 77 78 typedef struct F128_ALIGN_16 { 79 UX_FRACTION_DIGIT_TYPE digit[ NUM_X_FRACTION_DIGITS ]; 80 } _X_FLOAT; 81 82 #define G_X_DIGIT(p,n) (((_X_FLOAT *)(p))->DIGIT(n)) 83 #define P_X_DIGIT(p,n,v) (((_X_FLOAT *)(p))->DIGIT(n) = (v)) 84 #define X_TOGGLE_SIGN(p,v) (((_X_FLOAT *)(p))->DIGIT(0) ^= (v)) 85 86 #define SHIFT F_EXP_WIDTH 87 #define CSHIFT (BITS_PER_UX_FRACTION_DIGIT_TYPE - F_EXP_WIDTH) 88 89 90 typedef struct { 91 UX_SIGN_TYPE sign; 92 UX_EXPONENT_TYPE exponent; 93 UX_FRACTION_DIGIT_TYPE fraction[ NUM_UX_FRACTION_DIGITS ]; 94 } UX_FLOAT; 95 96 typedef struct { 97 UX_FRACTION_DIGIT_TYPE digits[ NUM_UX_FRACTION_DIGITS ]; 98 } FIXED_128; 99 100 #define UX_SIGN_SHIFT (BITS_PER_UX_FRACTION_DIGIT_TYPE - BITS_PER_UX_SIGN_TYPE) 101 #define UX_PRECISION 128 102 103 #define LSD_NUM (NUM_UX_FRACTION_DIGITS - 1) 104 #define MSD_NUM 0 105 106 #define G_UX_SIGN(x) (((UX_FLOAT*)(x))->sign) 107 #define G_UX_EXPONENT(x) (((UX_FLOAT*)(x))->exponent) 108 #define G_UX_MSD(x) (((UX_FLOAT*)(x))->fraction[0]) 109 #define G_UX_2nd_MSD(x) (((UX_FLOAT*)(x))->fraction[1]) 110 #define G_UX_LSD(x) (((UX_FLOAT*)(x))->fraction[LSD_NUM]) 111 #define G_UX_2nd_LSD(x) (((UX_FLOAT*)(x))->fraction[LSD_NUM-1]) 112 #define G_UX_FRACTION_DIGIT(x,n) (((UX_FLOAT*)(x))->fraction[n]) 113 114 #define P_UX_SIGN(x,v) ((((UX_FLOAT*)(x))->sign)=(v)) 115 #define P_UX_EXPONENT(x,v) ((((UX_FLOAT*)(x))->exponent)=(v)) 116 #define P_UX_MSD(x,v) ((((UX_FLOAT*)(x))->fraction[0])=(v)) 117 #define P_UX_2nd_MSD(x,v) ((((UX_FLOAT*)(x))->fraction[1])=(v)) 118 #define P_UX_LSD(x,v) ((((UX_FLOAT*)(x))->fraction[LSD_NUM])=(v)) 119 #define P_UX_2nd_LSD(x,v) ((((UX_FLOAT*)(x))->fraction[LSD_NUM-1])=(v)) 120 #define P_UX_FRACTION_DIGIT(x,n,v) (((UX_FLOAT*)(x))->fraction[n] = (v)) 121 122 #define UX_INCR_EXPONENT(x,v) ((((UX_FLOAT *)(x))->exponent) += (v)) 123 #define UX_DECR_EXPONENT(x,v) ((((UX_FLOAT *)(x))->exponent) -= (v)) 124 #define UX_TOGGLE_SIGN(x,v) ((((UX_FLOAT *)(x))->sign) ^= (v)) 125 126 #define UX_SIGN_BIT ((WORD) 1 << 31) 127 #define UX_MSB ((U_WORD)1 <<(BITS_PER_UX_FRACTION_DIGIT_TYPE-1)) 128 #define UX_OVERFLOW_EXPONENT (1 << F_EXP_WIDTH) 129 #define UX_UNDERFLOW_EXPONENT (- UX_OVERFLOW_EXPONENT) 130 #define UX_ZERO_EXPONENT (- (UX_EXPONENT_TYPE) 1 << (F_EXP_WIDTH + 2)) 131 #define UX_INFINITY_EXPONENT (-(UX_ZERO_EXPONENT + 1)) 132 133 134 #define AS_DIGIT(p,n) (((UX_FRACTION_DIGIT_TYPE *)(p))[n]) 135 136 #include "dpml_ux_32_64.h" 137 138 #define UX_LOW_FRACTION_IS_ZERO(p) (UX_OR_LOW_FRACTION_DIGITS(p) == 0) 139 #define UX_FRACTION_IS_ONE_HALF(p) ((G_UX_MSD(p) == UX_MSB) & \ 140 (UX_OR_LOW_FRACTION_DIGITS(p) == 0)) 141 142 #define UX_SET_SIGN_EXP_MSD(p,s,e,m) ( P_UX_SIGN(p,s), \ 143 P_UX_EXPONENT(p,e), \ 144 P_UX_MSD(p,m), \ 145 CLR_UX_LOW_FRACTION(p)) 146 147 #define UX_COPY(p,q) ( P_UX_SIGN(q, G_UX_SIGN(p)), \ 148 P_UX_EXPONENT(q, G_UX_EXPONENT(p)), \ 149 COPY_TO_UX_FRACTION(&G_UX_MSD(p),q)) 150 151 typedef U_WORD ERROR_CODE; 152 153 /******************************************************************************/ 154 /******************************************************************************/ 155 /** **/ 156 /** Name Macros **/ 157 /** **/ 158 /******************************************************************************/ 159 /******************************************************************************/ 160 161 /* 162 ** Following macros are defined to modify the interface of X_FLOAT routines 163 ** for different architectures variants at compile time. The macros are 164 ** defined as returnType_Arg1Arg2_PROTO. For example X_X_PROTO defines a 165 ** function which takes X_FLOAT argument and result is X_FLOAT argument. 166 ** 167 ** X_FLOAT_RES_OR_VOID defines what functions is returning. It can be void, 168 ** X_FLOAT or X_FLOAT *. 169 ** 170 ** X_FLOAT_RET_TYPE(x) defines the return type when result is part of the 171 ** argument list i.e a pointer is provided in the argument list to 172 ** put the result. It can be Nothing or X_FLOAT *x. 173 ** 174 ** X_FLOAT_ARG_TYPE(x) defines the argument type. It can be X_FLOAT *x, or 175 ** X_FLOAT x. 176 ** 177 ** X_FLOAT_INT_TYPE defines the integer type in the argument list. This should 178 ** be int in case of intel compilers. 179 ** 180 ** RETURN_X_FLOAT(x) defines the return statement of the function. It can be 181 ** be Nothing, return *x or return x 182 */ 183 184 #if defined(EMT64_LINUX_QUAD_INTERFACE) 185 # define X_FLOAT_RET_TYPE(x) 186 # define X_FLOAT_ARG_TYPE(x) _Quad x 187 # define X_FLOAT_INT_TYPE int 188 # define X_FLOAT_RES_OR_VOID _Quad 189 # define DECLARE_X_FLOAT(res) _X_FLOAT res; 190 # define PASS_RET_X_FLOAT(x) &x 191 //# define PASS_ARG_X_FLOAT(x) &x 192 # define PASS_ARG_X_FLOAT(x) (_X_FLOAT *) &x 193 # define RETURN_X_FLOAT(x) return *(_Quad *) &(x) 194 # define PACKED_ARG_IS_NEG(p) ((WORD)((_X_FLOAT *)(&p))->DIGIT(0) < 0) 195 196 #elif defined(X_NONVOID_RES_VAL_ARG_VAL) 197 # define X_FLOAT_RET_TYPE(x) 198 # define X_FLOAT_ARG_TYPE(x) _X_FLOAT x 199 # define X_FLOAT_INT_TYPE int 200 # define X_FLOAT_RES_OR_VOID _X_FLOAT 201 # define DECLARE_X_FLOAT(res) _X_FLOAT res; 202 # define PASS_RET_X_FLOAT(x) &x 203 # define PASS_ARG_X_FLOAT(x) &x 204 # define RETURN_X_FLOAT(x) return x; 205 # define PACKED_ARG_IS_NEG(p) ((WORD)((_X_FLOAT *)(&p))->DIGIT(0) < 0) 206 207 #elif defined(X_VOID_RES_REF_ARG_VAL) 208 # define X_FLOAT_RET_TYPE(x) _X_FLOAT *x, 209 # define X_FLOAT_ARG_TYPE(x) _X_FLOAT x 210 # define X_FLOAT_INT_TYPE int 211 # define X_FLOAT_RES_OR_VOID void 212 # define DECLARE_X_FLOAT(res) 213 # define PASS_RET_X_FLOAT(x) x 214 # define PASS_ARG_X_FLOAT(x) &x 215 # define RETURN_X_FLOAT(x) return; 216 # define PACKED_ARG_IS_NEG(p) ((WORD)((_X_FLOAT *)(&p))->DIGIT(0) < 0) 217 218 #else 219 # define X_FLOAT_RET_TYPE(x) _X_FLOAT *x, 220 # define X_FLOAT_ARG_TYPE(x) _X_FLOAT *x 221 # define X_FLOAT_INT_TYPE WORD 222 # define X_FLOAT_RES_OR_VOID void 223 # define DECLARE_X_FLOAT(res) 224 # define PASS_RET_X_FLOAT(x) x 225 # define PASS_ARG_X_FLOAT(x) x 226 # define RETURN_X_FLOAT(x) return; 227 # define PACKED_ARG_IS_NEG(p) ((WORD)((_X_FLOAT *)(p))->DIGIT(0) < 0) 228 #endif 229 230 #if !defined(X_FLOAT_INT_TYPE) 231 # define X_FLOAT_INT_TYPE WORD 232 #endif 233 234 235 # define X_I_PROTO(name,res,arg) \ 236 X_FLOAT_RES_OR_VOID name(X_FLOAT_RET_TYPE(res) int arg) 237 238 # define X_X_PROTO(name,res,arg) \ 239 X_FLOAT_RES_OR_VOID name(X_FLOAT_RET_TYPE(res) \ 240 X_FLOAT_ARG_TYPE(arg)) \ 241 242 # define X_XX_PROTO(name, res, arg1, arg2) \ 243 X_FLOAT_RES_OR_VOID name(X_FLOAT_RET_TYPE(res) \ 244 X_FLOAT_ARG_TYPE(arg1), X_FLOAT_ARG_TYPE(arg2)) \ 245 246 # define X_XI_PROTO(name, res, arg,i) \ 247 X_FLOAT_RES_OR_VOID name(X_FLOAT_RET_TYPE(res) \ 248 X_FLOAT_ARG_TYPE(arg), X_FLOAT_INT_TYPE i) \ 249 250 # define X_IX_PROTO(name, res, i, arg) \ 251 X_FLOAT_RES_OR_VOID name(X_FLOAT_RET_TYPE(res) \ 252 X_FLOAT_INT_TYPE i, X_FLOAT_ARG_TYPE(arg)) \ 253 254 # define X_XIptr_PROTO(name, res, arg,i) \ 255 X_FLOAT_RES_OR_VOID name(X_FLOAT_RET_TYPE(res) \ 256 X_FLOAT_ARG_TYPE(arg), X_FLOAT_INT_TYPE *i) \ 257 258 # define X_XXptr_PROTO(name, res, arg, p) \ 259 X_FLOAT_RES_OR_VOID name(X_FLOAT_RET_TYPE(res) \ 260 X_FLOAT_ARG_TYPE(arg), _X_FLOAT * p) \ 261 262 # define X_XXIptr_PROTO(name, res, arg1, arg2, i) \ 263 X_FLOAT_RES_OR_VOID name(X_FLOAT_RET_TYPE(res) \ 264 X_FLOAT_ARG_TYPE(arg1), X_FLOAT_ARG_TYPE(arg2), \ 265 X_FLOAT_INT_TYPE *i) \ 266 267 # define I_XXI_PROTO(name, arg1, arg2, i) \ 268 int name( X_FLOAT_ARG_TYPE(arg1), X_FLOAT_ARG_TYPE(arg2), int i) 269 270 # define RR_X_PROTO(name, res1, res2, arg) \ 271 void name(X_FLOAT_ARG_TYPE(arg), _X_FLOAT *res1, _X_FLOAT *res2) 272 273 274 /******************************************************************************/ 275 /******************************************************************************/ 276 /** **/ 277 /** Packed and Unpacked Constant Tables **/ 278 /** **/ 279 /******************************************************************************/ 280 /******************************************************************************/ 281 282 #if !defined(PACKED_CONSTANT_TABLE) 283 # define PACKED_CONSTANT_TABLE __TABLE_NAME(x_constants__ ) 284 #endif 285 286 #undef NAN 287 288 #if !defined(DPML_UX_CONS_FILE_NAME) 289 # define DPML_UX_CONS_FILE_NAME dpml_cons_x.h 290 #endif 291 292 #if !defined(BUILD_UX_CONS_TABLE) 293 # define INSTANTIATE_TABLE 0 294 # define INSTANTIATE_DEFINES 1 295 # include STR(DPML_UX_CONS_FILE_NAME) 296 #endif 297 298 /******************************************************************************/ 299 /******************************************************************************/ 300 /** **/ 301 /** Pack and Unpacked Routines **/ 302 /** **/ 303 /******************************************************************************/ 304 /******************************************************************************/ 305 306 /* 307 ** There's a slight complication here because the interface to these routines 308 ** depend on the interface to the exception handler. Specifically, if we 309 ** need to pass the original arguments and/or the name of the function to the 310 ** exception handler, that information must be passed to pack and unpack. 311 */ 312 313 typedef struct { 314 U_WORD arg_classes; 315 char * name; 316 _X_FLOAT * args[2]; 317 } UX_EXCEPTION_INFO_STRUCT; 318 319 #define EXCPTN_INFO __INTERNAL_NAME(ux_excptn_info__) 320 321 #define EXCEPTION_INFO_DECL UX_EXCEPTION_INFO_STRUCT EXCEPTION_INFO; 322 #define OPT_EXCEPTION_INFO , &EXCEPTION_INFO 323 #define OPT_EXCEPTION_INFO_DECLARATION , UX_EXCEPTION_INFO_STRUCT * EXCPTN_INFO 324 #define OPT_EXCEPTION_INFO_ARGUMENT , EXCPTN_INFO 325 #define IF_OPTNL_ERROR_INFO(x) x 326 327 328 329 #if (EXCEPTION_INTERFACE_SEND & send_function_name ) 330 # define INIT_EXCEPTION_INFO EXCPTN_INFO.name = STR(F_ENTRY_NAME) 331 #else 332 # define INIT_EXCEPTION_INFO 333 #endif 334 335 #define UNPACK(a,b,c,d) UNPACK_X_OR_Y(a,0,b,c,d) 336 337 #if !defined( UNPACK_X_OR_Y ) 338 # define UNPACK_X_OR_Y __INTERNAL_NAME( unpack_x_or_y__ ) 339 #endif 340 341 #if !defined( UNPACK2 ) 342 # define UNPACK2 __INTERNAL_NAME( unpack2__ ) 343 #endif 344 345 #if !defined( PACK ) 346 # define PACK __INTERNAL_NAME( pack__ ) 347 #endif 348 349 extern WORD UNPACK_X_OR_Y ( 350 _X_FLOAT *, /* packed argument 1 */ 351 _X_FLOAT *, /* packed argument 2 */ 352 UX_FLOAT *, /* unpacked argument */ 353 U_WORD const *, /* class-to-action map */ 354 _X_FLOAT * /* packed result */ 355 OPT_EXCEPTION_INFO_DECLARATION 356 ); 357 358 extern WORD UNPACK2 ( 359 _X_FLOAT *, /* packed argument 1 */ 360 _X_FLOAT *, /* packed argument 2 */ 361 UX_FLOAT *, /* unpacked argument 1 */ 362 UX_FLOAT *, /* unpacked argument 2 */ 363 U_WORD const *, /* class-to-action map */ 364 _X_FLOAT * /* packed result */ 365 OPT_EXCEPTION_INFO_DECLARATION 366 ); 367 368 369 extern void PACK ( 370 UX_FLOAT *, /* unpacked result */ 371 _X_FLOAT *, /* packed result */ 372 ERROR_CODE, /* underflow code */ 373 ERROR_CODE /* overflow code */ 374 OPT_EXCEPTION_INFO_DECLARATION 375 ); 376 377 /* 378 ** Include the class-to-action-mapping definitions here, since they are used 379 ** primarily by the unpack routines. 380 */ 381 382 #define INDEX_POS 0 383 #define INDEX_WIDTH 3 384 #define INDEX_MASK 0x7 385 386 #define ACTION_POS 3 387 #define ACTION_WIDTH 3 388 #define ACTION_MASK 0x7 389 390 #define CLASS_TO_ACTION(class, action, index) \ 391 (((action << INDEX_WIDTH) | (index)) << \ 392 ((INDEX_WIDTH + ACTION_WIDTH)*(class))) 393 #define CLASS_TO_ACTION_DISP(n) \ 394 ((n) << ((INDEX_WIDTH + ACTION_WIDTH)*F_C_NUM_CLASSES)) 395 396 #define RETURN_UNPACKED 0 397 #define RETURN_QUIET_NAN 1 398 #define RETURN_VALUE 2 399 #define RETURN_NEGATIVE 3 400 #define RETURN_ABSOLUTE 4 401 #define RETURN_CPYSN_ARG_0 5 402 #define RETURN_ERROR 7 403 404 #define CLASS_TO_INDEX_WIDTH 4 405 #define CLASS_TO_INDEX(n,m) ((m) << ((n)*CLASS_TO_INDEX_WIDTH)) 406 #define CLASS_TO_INDEX_MASK MAKE_MASK(CLASS_TO_INDEX_WIDTH, 0) 407 #define WORDS_PER_CLASS_TO_ACTION_MAP (64/BITS_PER_WORD) 408 409 /******************************************************************************/ 410 /******************************************************************************/ 411 /** **/ 412 /** Rational Evaluation Routine **/ 413 /** **/ 414 /******************************************************************************/ 415 /******************************************************************************/ 416 417 #if !defined( EVALUATE_RATIONAL ) 418 # define EVALUATE_RATIONAL __INTERNAL_NAME( evaluate_rational__ ) 419 #endif 420 421 extern void EVALUATE_RATIONAL( 422 UX_FLOAT *, /* Argument */ 423 FIXED_128 *, /* Coefficient array */ 424 U_WORD, /* Number of coefficients */ 425 U_WORD, /* Evaluation flags */ 426 UX_FLOAT * /* Result */ 427 ); 428 429 #define STANDARD 0x001 430 #define POST_MULTIPLY 0x002 431 #define SQUARE_TERM 0x004 432 #define ALTERNATE_SIGN 0x008 433 434 #define NUM_DEN_FIELD_WIDTH 4 435 436 #define NO_DIVIDE ((WORD) 1 << (2*NUM_DEN_FIELD_WIDTH)) 437 #define SWAP ((WORD) 2 << (2*NUM_DEN_FIELD_WIDTH)) 438 #define SKIP ((WORD) 4 << (2*NUM_DEN_FIELD_WIDTH)) 439 440 #define SCALE_WIDTH 6 441 #define SCALE_POS (BITS_PER_WORD - SCALE_WIDTH) 442 #define P_SCALE(n) (((WORD) (n)) << SCALE_POS) 443 #define G_SCALE(n) (((WORD) (n)) >> SCALE_POS) 444 445 #define POLY_SHIFT(u,n) ((((UX_FLOAT *)(u))->exponent)*(n)) 446 #define NUMERATOR_FLAGS(n) (n) 447 #define DENOMINATOR_FLAGS(n) ((n) << NUM_DEN_FIELD_WIDTH) 448 449 #if !defined(EVALUATE_PACKED_POLY) 450 # define EVALUATE_PACKED_POLY __INTERNAL_NAME(evaluate_packed_poly__) 451 #endif 452 453 void 454 EVALUATE_PACKED_POLY( UX_FLOAT * argument, WORD degree, FIXED_128 * coefs, 455 U_WORD mask, WORD bias, UX_FLOAT * result); 456 457 /******************************************************************************/ 458 /******************************************************************************/ 459 /** **/ 460 /** Rational Evaluation Routine **/ 461 /** **/ 462 /******************************************************************************/ 463 /******************************************************************************/ 464 465 #if !defined( ADDSUB ) 466 # define ADDSUB __INTERNAL_NAME( addsub__ ) 467 #endif 468 469 extern void ADDSUB( 470 UX_FLOAT *, /* arg1 */ 471 UX_FLOAT *, /* arg2 */ 472 U_WORD, /* operation flags */ 473 UX_FLOAT * /* result */ 474 ); 475 476 /* 477 ** The logic of the add/sub routine depends on theses symbols have 478 ** these *SPECIFIC* values. !!! DO NOT CHANGE THEM !!! 479 */ 480 481 #define ADD 0 482 #define SUB 1 483 #define ADD_SUB 2 484 #define SUB_ADD 3 485 #define MAGNITUDE_ONLY 4 486 #define NO_NORMALIZATION 8 487 488 489 /******************************************************************************/ 490 /******************************************************************************/ 491 /** **/ 492 /** Round to Integer Routine **/ 493 /** **/ 494 /******************************************************************************/ 495 /******************************************************************************/ 496 497 #if !defined(UX_RND_TO_INT) 498 # define UX_RND_TO_INT __INTERNAL_NAME(ux_rnd_to_int__) 499 #endif 500 501 extern WORD UX_RND_TO_INT( /* return val is integer part as int */ 502 UX_FLOAT *, /* argument */ 503 WORD, /* rounding mode bit vector */ 504 UX_FLOAT *, /* Integer part as float, ignored if 0 */ 505 UX_FLOAT *); /* fraction part, ignored if 0 */ 506 507 #define RZ_BIT_VECTOR 0x0000 /* 0000 0000 0000 0000 */ 508 #define RP_BIT_VECTOR 0x00fa /* 0000 0000 1111 1010 */ 509 #define RM_BIT_VECTOR 0xfa00 /* 1111 1010 0000 0000 */ 510 #define RN_BIT_VECTOR 0xa8a8 /* 1010 1000 1010 1000 */ 511 #define RV_BIT_VECTOR 0xaaaa /* 1010 1010 1010 1010 */ 512 513 #define INTEGER_RESULT 0x10000 514 #define FRACTION_RESULT 0x20000 515 516 /******************************************************************************/ 517 /******************************************************************************/ 518 /** **/ 519 /** Normalization Routines **/ 520 /** **/ 521 /******************************************************************************/ 522 /******************************************************************************/ 523 524 #if !defined(FFS_AND_SHIFT) 525 # define FFS_AND_SHIFT __INTERNAL_NAME(ffs_and_shift__) 526 #endif 527 528 extern WORD FFS_AND_SHIFT( /* returns shift count */ 529 UX_FLOAT *, /* source and destination */ 530 U_WORD); /* 'opcode' */ 531 532 #define FFS_NORMALIZE 0 533 #define FFS_CVT_WORD 1 534 #define FFS_CVT_U_WORD 2 535 536 #define NORMALIZE(x) FFS_AND_SHIFT(x, FFS_NORMALIZE) 537 #define WORD_TO_UX(n,x) (P_UX_MSD(x, n), FFS_AND_SHIFT(x, FFS_CVT_WORD)) 538 #define U_WORD_TO_UX(n,x) (P_UX_MSD(x, n), FFS_AND_SHIFT(x, FFS_CVT_U_WORD)) 539 540 /******************************************************************************/ 541 /******************************************************************************/ 542 /** **/ 543 /** Radian Trig Prototypes **/ 544 /** **/ 545 /******************************************************************************/ 546 /******************************************************************************/ 547 548 #if !defined(UX_SINCOS) 549 # define UX_SINCOS __INTERNAL_NAME(ux_sincos) 550 #endif 551 552 extern WORD UX_SINCOS( 553 UX_FLOAT *, /* unpacked_argument */ 554 WORD, /* octant */ 555 WORD, /* function_code, */ 556 UX_FLOAT *); /* unpacked_result */ 557 558 #define DEGREE 16 559 560 #define SIN_FUNC 1 561 #define COS_FUNC 2 562 #define SINCOS_FUNC (SIN_FUNC | COS_FUNC) 563 564 #define SIND_FUNC (SIN_FUNC | DEGREE) 565 #define COSD_FUNC (COS_FUNC | DEGREE) 566 #define SINCOSD_FUNC (SINCOS_FUNC | DEGREE) 567 568 #define TAN_FUNC 4 569 #define COT_FUNC 8 570 571 #define TAND_FUNC (TAN_FUNC | DEGREE) 572 #define COTD_FUNC (COT_FUNC | DEGREE) 573 574 #define SIN(a,b) EVAL_SINCOS(a, 0, SIN_FUNC, b) 575 #define COS(a,b) EVAL_SINCOS(a, 0, COS_FUNC, b) 576 #define SINCOS(a,b) EVAL_SINCOS(a, 0, SINCOS_FUNC, b) 577 578 #define SINCOS_COEF_ARRAY_LENGTH 12 579 extern FIXED_128 sincos_coef_array[2*SINCOS_COEF_ARRAY_LENGTH]; 580 581 /******************************************************************************/ 582 /******************************************************************************/ 583 /** **/ 584 /** Log Prototypes **/ 585 /** **/ 586 /******************************************************************************/ 587 /******************************************************************************/ 588 589 #if !defined(UX_LOG) 590 # define UX_LOG __INTERNAL_NAME( ux_log__ ) 591 #endif 592 593 extern void UX_LOG( 594 UX_FLOAT *, /* Argument */ 595 UX_FLOAT *, /* scale - LOG(x) = scale*log2(x) */ 596 UX_FLOAT *); /* Result */ 597 598 #define LOG(a,b) UX_LOG( a, & UX_CON( LN_2 ), b) 599 600 601 #if !defined(UX_LOG_POLY) 602 # define UX_LOG_POLY __INTERNAL_NAME( ux_log_poly__ ) 603 #endif 604 605 extern void UX_LOG_POLY( 606 UX_FLOAT *, /* Argument */ 607 UX_FLOAT *); /* Result */ 608 609 /******************************************************************************/ 610 /******************************************************************************/ 611 /** **/ 612 /** Miscellaneous Prototypes **/ 613 /** **/ 614 /******************************************************************************/ 615 /******************************************************************************/ 616 617 #if !defined( EXP ) 618 # define UX_EXP __INTERNAL_NAME( ux_exp__ ) 619 #endif 620 621 extern void UX_EXP( 622 UX_FLOAT *, /* argument */ 623 UX_FLOAT * /* result */ 624 ); 625 626 #if !defined( DIVIDE ) 627 # define DIVIDE __INTERNAL_NAME( divide__ ) 628 #endif 629 630 extern void DIVIDE( 631 UX_FLOAT *, /* numerator - assume 1 if ptr is 0 */ 632 UX_FLOAT *, /* denominator */ 633 U_WORD, /* result precision */ 634 UX_FLOAT * /* result */ 635 ); 636 637 #define HALF_PRECISION 1 638 #define FULL_PRECISION 2 639 640 #if !defined( MULTIPLY ) 641 # define MULTIPLY __INTERNAL_NAME( multiply__ ) 642 #endif 643 644 extern void MULTIPLY( 645 UX_FLOAT *, /* arg1 */ 646 UX_FLOAT *, /* arg1 */ 647 UX_FLOAT * /* result */ 648 ); 649 650 #define SQUARE(a,b) MULTIPLY(a, a, b) 651 652 #if !defined( EXTENDED_MULTIPLY ) 653 # define EXTENDED_MULTIPLY __INTERNAL_NAME( extended_multiply__ ) 654 #endif 655 656 extern void EXTENDED_MULTIPLY( 657 UX_FLOAT *, /* arg1 */ 658 UX_FLOAT *, /* arg1 */ 659 UX_FLOAT *, /* hi result */ 660 UX_FLOAT * /* lo result */ 661 ); 662 663 #if !defined(UX_SQRT_EVALUATION) 664 # define UX_SQRT_EVALUATION __INTERNAL_NAME( ux_sqrt_evaluation__ ) 665 #endif 666 667 #define EVALUATE_SQRT 0 668 #define EVALUATE_RSQRT 1 669 670 671 extern void UX_SQRT_EVALUATION( 672 UX_FLOAT *, /* Argument */ 673 WORD, /* evaluation type - sqrt or rsqrt */ 674 UX_FLOAT *); /* Result */ 675 676 677 #define UX_SQRT(a,b) UX_SQRT_EVALUATION(a, EVALUATE_SQRT, b) 678 679 #if !defined(HYPOT) 680 # define HYPOT __INTERNAL_NAME( hypot__ ) 681 #endif 682 683 extern void HYPOT( 684 UX_FLOAT *, /* Argument 1 */ 685 UX_FLOAT *, /* Argument 2 */ 686 UX_FLOAT *); /* Result */ 687 688 689 /******************************************************************************/ 690 /******************************************************************************/ 691 /** **/ 692 /** Miscellaneous Definitions **/ 693 /** **/ 694 /******************************************************************************/ 695 /******************************************************************************/ 696 697 #define NONE 0 698 #define NOT_USED 0 699 700 #if defined(NULL) 701 # undef NULL 702 #endif 703 #define NULL 0 704 705 #if defined GROUP 706 # define D_GROUP(x) GROUP(x) 707 #else 708 # define D_GROUP_NAME PASTE_2(__INTERNAL_NAME(group),_d) 709 extern double D_GROUP_NAME( double ); 710 # define D_GROUP(x) D_GROUP_NAME(x) 711 #endif 712 713 714 /******************************************************************************/ 715 /******************************************************************************/ 716 /** **/ 717 /** MPHOC Macros for Class-to-Action Table Definitions **/ 718 /** **/ 719 /******************************************************************************/ 720 /******************************************************************************/ 721 722 #define POS 0 723 #define NEG UX_SIGN_BIT 724 725 #if defined(MAKE_INCLUDE) 726 727 # define PRINT_64_TBL_ITEM(i) \ 728 printf( "\t/* %3i */ %#16.4.16i,\n", BYTES(MP_BIT_OFFSET), i);\ 729 MP_BIT_OFFSET += 64 730 731 # define PRINT_UX_FRACTION_DIGIT_TBL_ITEM(val) PRINT_64_TBL_ITEM(val) 732 733 # define PRINT_CLASS_TO_ACTION_TBL_DEF(name) \ 734 printf("#define\t" name "\t((U_WORD const *) ((char *) "\ 735 STR(MP_TABLE_NAME) " + %i))\n", BYTES(MP_BIT_OFFSET)) 736 737 # define PRINT_UX_FRACTION_DIGIT_TBL_VDEF(name) \ 738 printf("#define\t" name \ 739 "\t*((UX_FRACTION_DIGIT_TYPE *) ((char *) " \ 740 STR(MP_TABLE_NAME) " + %i))\n", BYTES(MP_BIT_OFFSET)) 741 742 # define PRINT_UX_FRACTION_DIGIT_TBL_VDEF_ITEM(name, val) \ 743 printf("#define\t" name \ 744 "\t*((UX_FRACTION_DIGIT_TYPE *) ((char *) " \ 745 STR(MP_TABLE_NAME) " + %i))\n", BYTES(MP_BIT_OFFSET)); \ 746 PRINT_64_TBL_ITEM(val) 747 748 # define PRINT_FIXED_128_TBL_ADEF(name) \ 749 printf("#define\t" name "\t((FIXED_128 *) ((char *) " \ 750 STR(MP_TABLE_NAME) " + %i))\n", BYTES(MP_BIT_OFFSET)) 751 752 # define PRINT_UX_FRACTION_DIGIT_TBL_ADEF(name) \ 753 printf("#define\t" name "\t((UX_FRACTION_DIGIT_TYPE *) ((char *) " \ 754 STR(MP_TABLE_NAME) " + %i))\n", BYTES(MP_BIT_OFFSET)) 755 756 # define PRINT_UX_TBL_ADEF(name) \ 757 printf("#define\t" name "\t((UX_FLOAT *) ((char *) " \ 758 STR(MP_TABLE_NAME) " + %i))\n", BYTES(MP_BIT_OFFSET)) 759 760 # define PRINT_UX_TBL_ITEM(val) \ 761 MP_BIT_OFFSET = print_ux_table_value(val, MP_BIT_OFFSET) 762 763 # define PRINT_UX_TBL_ADEF_ITEM(name, val) \ 764 PRINT_UX_TBL_ADEF(name); PRINT_UX_TBL_ITEM(val) 765 766 @divert divertText 767 print_ux_fraction_digits(value)768 function print_ux_fraction_digits(value) 769 { 770 auto hi, i; 771 772 if (value >= 1) 773 { 774 printf("ERROR: value out of range in print_ux_fraction_digits\n"); 775 exit; 776 } 777 778 for (i = NUM_UX_FRACTION_DIGITS; i > 0; i--) 779 { 780 value = bldexp(value, BITS_PER_UX_FRACTION_DIGIT_TYPE); 781 hi = trunc(value); 782 if (hi) 783 printf( DIGIT_FORMAT, hi); 784 else 785 printf( ZERO_FORMAT ); 786 value -= hi; 787 } 788 printf("\n"); 789 790 return value; 791 } 792 793 print_ux_table_value(value,offset)794 function print_ux_table_value(value, offset) 795 { 796 auto exponent, hi, sign_bit, i; 797 798 sign_bit = 0; 799 if (value == 0) 800 exponent = bldexp(-1, F_EXP_WIDTH + 2); 801 else 802 { 803 exponent = bexp(value); 804 if (value < 0) 805 { 806 sign_bit = 1; 807 value = -value; 808 } 809 value = bldexp(value, -exponent); 810 } 811 812 if (sign_bit) 813 printf("\t/* %3i */ NEG, %4i,", BYTES(offset), exponent); 814 else 815 printf("\t/* %3i */ POS, %4i,", BYTES(offset), exponent); 816 817 print_ux_fraction_digits(value); 818 return offset + BITS_PER_UX_SIGN_TYPE + BITS_PER_UX_EXPONENT_TYPE + 819 UX_PRECISION; 820 } 821 822 find_max_exponent(degree,index)823 function find_max_exponent(degree, index) 824 { 825 auto i, max_exponent; 826 827 max_exponent = -128; 828 for (i = 0; i <= degree; i++) 829 { 830 exponent = bexp(bround(ux_rational_coefs[index + i], 128)); 831 if (exponent > max_exponent) 832 max_exponent = exponent; 833 } 834 return max_exponent; 835 } 836 837 838 /* 839 ** The following routine prints out coefficients in the array 840 ** 'ux_rational_coefs' in fixed point format. 841 */ 842 print_ux_poly_coefs(pad_len,degree,final_scale,index)843 procedure print_ux_poly_coefs(pad_len, degree, final_scale, index) 844 { 845 auto scale, exponent, i; 846 847 for (i = 0; i < pad_len; i++) 848 { 849 printf( "\t/* %3i */ %#32.4.16i,\n", BYTES(MP_BIT_OFFSET), 0); 850 MP_BIT_OFFSET += 128; 851 } 852 853 exponent = find_max_exponent(degree, index); 854 scale = 128 - exponent; 855 index += degree; 856 for (i = degree; i >= 0; i--) 857 { 858 printf( "\t/* %3i */ %#32.4.16i,\n", BYTES(MP_BIT_OFFSET), 859 abs(nint(bldexp(ux_rational_coefs[index], scale )))); 860 MP_BIT_OFFSET += 128; 861 index--; 862 } 863 PRINT_U_TBL_ITEM(exponent + final_scale); 864 } 865 print_ux_rational_coefs(num_degree,den_degree,scale)866 function print_ux_rational_coefs( num_degree, den_degree, scale) 867 { 868 auto max_degree; 869 870 max_degree = max(num_degree, den_degree); 871 print_ux_poly_coefs(max_degree - num_degree , num_degree, scale, 0); 872 873 if (den_degree) 874 print_ux_poly_coefs(max_degree - den_degree, den_degree, 0, 875 num_degree + 1); 876 877 return max_degree; 878 } 879 880 /* 881 ** This routine finds the "width" and "bias" for converting MP numbers 882 ** to a special 128 bit packed format used for special polynomial 883 ** evaluations. The coefficients are contained in the global array 884 ** ux_rational_coef and the both the width and the bias are returned 885 ** via global values. See the description in dpml_ux_ops.c 886 */ 887 find_exponent_width_and_bias(degree,base_index)888 procedure find_exponent_width_and_bias(degree, base_index) 889 { 890 auto i, top, _diff, min_diff, max_diff, old_exp, new_exp, width; 891 892 top = base_index + degree; 893 min_diff = max_diff = 0; 894 old_exp = 0; 895 for (i = base_index; i <= top; i++) 896 { 897 new_exp = bexp(ux_rational_coefs[i]); 898 _diff = new_exp - old_exp; 899 if (_diff < min_diff) 900 min_diff = _diff; 901 else if (_diff > max_diff) 902 max_diff = _diff; 903 old_exp = new_exp; 904 } 905 906 _diff = max_diff - min_diff + 1; 907 width = bexp(_diff); 908 if (bldexp(.5, width) == _diff) 909 width--; 910 packed_exponent_width = width; 911 packed_exponent_bias = -min_diff; 912 } 913 914 /* 915 ** After we know the bias and the width, we need to pack the coefficient 916 ** values 917 */ 918 cvt_to_packed(degree,base_index,width,bias)919 procedure cvt_to_packed(degree, base_index, width, bias) 920 { 921 auto i, top, num_bits, tmp, old_exp, new_exp, sign_bit; 922 923 find_exponent_width_and_bias(degree, base_index); 924 top = base_index + degree; 925 old_exp = 0; 926 num_bits = UX_PRECISION - width - 1; 927 for (i = base_index; i <= top; i++) 928 { 929 sign_bit = 0; 930 tmp = bround(ux_rational_coefs[i], num_bits); 931 if (tmp < 0) 932 { 933 tmp = -tmp; 934 sign_bit = 1; 935 } 936 new_exp = bexp(tmp); 937 tmp = nint(bldexp(tmp, num_bits - new_exp)); 938 tmp = bldexp(tmp, width + 1) + 2*(new_exp - old_exp + bias) + 939 sign_bit; 940 old_exp = new_exp; 941 ux_rational_coefs[i] = tmp; 942 } 943 } 944 945 /* 946 ** After converting to pack format, we need to print them out 947 */ 948 print_packed(degree,base_index)949 procedure print_packed(degree, base_index) 950 { 951 auto i, top; 952 953 top = base_index + degree; 954 for (i = degree; i >= 0; i--) 955 { 956 printf( "\t/* %3i */ %#32.4.16i,\n", BYTES(MP_BIT_OFFSET), 957 ux_rational_coefs[top--]); 958 MP_BIT_OFFSET += 128; 959 } 960 } 961 962 @end_divert 963 964 #endif 965 966 967 #if !defined(EXTENDED_DIGIT_MULTIPLY) 968 # define EXTENDED_DIGIT_MULTIPLY(a,b,h,l) (l) = (a)*(b); UMULH(a,b,h) 969 #endif 970 971 #endif 972