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