summaryrefslogtreecommitdiffstats
path: root/private/fp32/include/trans.h
blob: 3e5c66f954fe207548e071d400e0075961edc7fa (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
/***
*trans.h - definitions for computing transcendentals
*
*	Copyright (c) 1991-1991, Microsoft Corporation.	All rights reserved.
*
*Purpose: Define constants and macros that are used for computing
*   transcendentals. Some of the definitions are machine dependent.
*   Double is assumed to conform to the IEEE 754 std format.
*
*Revision History:
*   08-14-91	GDP	written
*   10-29-91	GDP	removed unused prototypes, added _frnd
*   01-20-92	GDP	significant changes -- IEEE exc. support
*   03-27-92	GDP	put IEEE definitions in fpieee.h
*   03-31-92	GDP	add internal constants for _ctrlfp, _statfp
*   05-08-92    PLM     added M68K switch
*   05-18-92    XY      added exception macro under M68K switch
*   06-23-92    GDP     added macro for negative zero
*   09-06-92    GDP     include cruntime.h, calling convention macros
*   07-16-93    SRW     ALPHA Merge
*   01-13-94    RDL	Added #ifndef _LANGUAGE_ASSEMBLY for asm includes.
*   10-02-94    BWT     PPC merge
*
*******************************************************************************/
#ifndef _INC_TRANS

#ifdef __cplusplus
extern "C" {
#endif

#ifndef _LANGUAGE_ASSEMBLY

#include <cruntime.h>

/*
 * Conditional macro definition for function calling type and variable type
 * qualifiers.
 */
#if   ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )

/*
 * Definitions for MS C8-32 (386/486) compiler
 */
#define _CRTAPI1 __cdecl
#define _CRTAPI2 __cdecl

#elif ( _MSC_VER == 600 )

/*
 * Definitions for old MS C6-386 compiler
 */
#define _CRTAPI1 _cdecl
#define _CRTAPI2 _cdecl
#define _CRTVAR1 _cdecl
#define _M_IX86  300

#else

/*
 * Other compilers (e.g., MIPS)
 */
#define _CRTAPI1
#define _CRTAPI2
#define _CRTVAR1

#endif

#include <fpieee.h>

#define D_BIASM1 0x3fe /* off by one to compensate for the implied bit */

#ifdef B_END
/* big endian */
#define D_EXP(x) ((unsigned short *)&(x))
#define D_HI(x) ((unsigned long *)&(x))
#define D_LO(x) ((unsigned long *)&(x)+1)
#else
#define D_EXP(x) ((unsigned short *)&(x)+3)
#define D_HI(x) ((unsigned long *)&(x)+1)
#define D_LO(x) ((unsigned long *)&(x))
#endif

/* return the int representation of the exponent
 * if x = .f * 2^n, 0.5<=f<1, return n (unbiased)
 * e.g. INTEXP(3.0) == 2
 */
#define INTEXP(x) ((signed short)((*D_EXP(x) & 0x7ff0) >> 4) - D_BIASM1)


/* check for infinity, NAN */
#define D_ISINF(x) ((*D_HI(x) & 0x7fffffff) == 0x7ff00000 && *D_LO(x) == 0)
#define IS_D_SPECIAL(x)	((*D_EXP(x) & 0x7ff0) == 0x7ff0)
#define IS_D_NAN(x) (IS_D_SPECIAL(x) && !D_ISINF(x))

#ifdef  _M_MRX000

#define IS_D_SNAN(x)	((*D_EXP(x) & 0x7ff8) == 0x7ff8)
#define IS_D_QNAN(x)	((*D_EXP(x) & 0x7ff8) == 0x7ff0 && \
			 (*D_HI(x) << 13 || *D_LO(x)))
#else

#define IS_D_QNAN(x)	((*D_EXP(x) & 0x7ff8) == 0x7ff8)
#define IS_D_SNAN(x)	((*D_EXP(x) & 0x7ff8) == 0x7ff0 && \
			 (*D_HI(x) << 13 || *D_LO(x)))
#endif

#define IS_D_DENORM(x)	((*D_EXP(x) & 0x7ff0) == 0  && \
			 (*D_HI(x) << 12 || *D_LO(x)))


#define IS_D_INF(x)  (*D_HI(x) == 0x7ff00000 && *D_LO(x) == 0)
#define IS_D_MINF(x) (*D_HI(x) == 0xfff00000 && *D_LO(x) == 0)

#ifdef  _M_MRX000
#define D_IND_HI 0x7ff7ffff
#define D_IND_LO 0xffffffff
#else
#define D_IND_HI 0xfff80000
#define D_IND_LO 0x0
#endif

typedef union	{
    long lng[2];
    double dbl;
    } _dbl;

extern _dbl _d_inf;
extern _dbl _d_ind;
extern _dbl _d_max;
extern _dbl _d_min;
extern _dbl _d_mzero;

#define D_INF  (_d_inf.dbl)
#define D_IND  (_d_ind.dbl)
#define D_MAX  (_d_max.dbl)
#define D_MIN  (_d_min.dbl)
#define D_MZERO	(_d_mzero.dbl)	     /* minus zero */

/* min and max exponents for normalized numbers in the
 * form: 0.xxxxx... * 2^exp (NOT 1.xxxx * 2^exp !)
 */
#define MAXEXP 1024
#define MINEXP -1021

#endif  /* _LANGUAGE_ASSEMBLY */


#if defined(_M_IX86)


/* Control word for computation of transcendentals */
#define ICW	   0x133f

#define IMCW	   0xffff

#define IMCW_EM 	0x003f		/* interrupt Exception Masks */
#define IEM_INVALID	0x0001		/*   invalid */
#define IEM_DENORMAL	0x0002		/*   denormal */
#define IEM_ZERODIVIDE	0x0004		/*   zero divide */
#define IEM_OVERFLOW	0x0008		/*   overflow */
#define IEM_UNDERFLOW	0x0010		/*   underflow */
#define IEM_INEXACT	0x0020		/*   inexact (precision) */


#define IMCW_RC	0x0c00			/* Rounding Control */
#define IRC_CHOP	0x0c00		/*   chop */
#define IRC_UP		0x0800		/*   up */
#define IRC_DOWN	0x0400		/*   down */
#define IRC_NEAR	0x0000		/*   near */

#define ISW_INVALID	0x0001		/* invalid */
#define ISW_DENORMAL	0x0002		/* denormal */
#define ISW_ZERODIVIDE	0x0004		/* zero divide */
#define ISW_OVERFLOW	0x0008		/* overflow */
#define ISW_UNDERFLOW	0x0010		/* underflow */
#define ISW_INEXACT	0x0020		/* inexact (precision) */

#define IMCW_PC 	0x0300		/* Precision Control */
#define IPC_24		0x0000		/*    24 bits */
#define IPC_53		0x0200		/*    53 bits */
#define IPC_64		0x0300		/*    64 bits */

#define IMCW_IC 	0x1000		/* Infinity Control */
#define IIC_AFFINE	0x1000		/*   affine */
#define IIC_PROJECTIVE	0x0000		/*   projective */


#elif defined(_M_MRX000)


#define ICW		0x00000f80		/* Internal CW for transcendentals */
#define IMCW		0xffffff83		/* Internal CW Mask */

#define IMCW_EM 	0x00000f80		/* interrupt Exception Masks */
#define IEM_INVALID	0x00000800		/*   invalid */
#define IEM_ZERODIVIDE	0x00000400		/*   zero divide */
#define IEM_OVERFLOW	0x00000200		/*   overflow */
#define IEM_UNDERFLOW	0x00000100		/*   underflow */
#define IEM_INEXACT	0x00000080		/*   inexact (precision) */


#define IMCW_RC 	0x00000003		/* Rounding Control */
#define IRC_CHOP	0x00000001		/*   chop */
#define IRC_UP		0x00000002		/*   up */
#define IRC_DOWN	0x00000003		/*   down */
#define IRC_NEAR	0x00000000		/*   near */


#define ISW_INVALID	(1<<6)	/* invalid */
#define ISW_ZERODIVIDE	(1<<5)	/* zero divide */
#define ISW_OVERFLOW	(1<<4)	/* overflow */
#define ISW_UNDERFLOW	(1<<3)	/* underflow */
#define ISW_INEXACT	(1<<2)	/* inexact (precision) */


#elif defined(_M_ALPHA)


//
// ICW is the Internal Control Word for transcendentals: all five exceptions
// are masked and round to nearest mode is set. IMCW is the mask: all bits
// are set, except for the ISW bits.
//

#define ICW (IEM_INEXACT | IEM_UNDERFLOW | IEM_OVERFLOW | IEM_ZERODIVIDE | IEM_INVALID | IRC_NEAR)
#define ISW (ISW_INEXACT | ISW_UNDERFLOW | ISW_OVERFLOW | ISW_ZERODIVIDE | ISW_INVALID)
#define IMCW (0xffffffff ^ ISW)

//
// The defines for the internal control word match the format of the Alpha
// AXP software FPCR except for the rounding mode which is obtained from the
// Alpha AXP hardware FPCR and shifted right 32 bits.
//

//
// Internal Exception Mask bits.
// Each bit _disables_ an exception (they are not _enable_ bits).
//

#define IMCW_EM 	0x0000003e	/* interrupt Exception Masks */

#define IEM_INEXACT	0x00000020	/*   inexact (precision) */
#define IEM_UNDERFLOW	0x00000010	/*   underflow */
#define IEM_OVERFLOW	0x00000008	/*   overflow */
#define IEM_ZERODIVIDE	0x00000004	/*   zero divide */
#define IEM_INVALID	0x00000002	/*   invalid */

//
// Internal Rounding Control values.
//

#define IMCW_RC 	(0x3 << 26)	/* Rounding Control */

#define IRC_CHOP	(0x0 << 26)	/*   chop */
#define IRC_DOWN	(0x1 << 26)	/*   down */
#define IRC_NEAR	(0x2 << 26)	/*   near */
#define IRC_UP		(0x3 << 26)	/*   up */

//
// Internal Status Word bits.
//

#define ISW_INEXACT	0x00200000	/* inexact (precision) */
#define ISW_UNDERFLOW	0x00100000	/* underflow */
#define ISW_OVERFLOW	0x00080000	/* overflow */
#define ISW_ZERODIVIDE	0x00040000	/* zero divide */
#define ISW_INVALID	0x00020000	/* invalid */


#elif defined(_M_PPC)


#define IMCW_EM         0x000000f8	/* Exception Enable Mask    */

#define IEM_INVALID     0x00000080	/*   invalid                */
#define IEM_OVERFLOW    0x00000040	/*   overflow               */
#define IEM_UNDERFLOW   0x00000020	/*   underflow              */
#define IEM_ZERODIVIDE  0x00000010      /*   zero divide            */
#define IEM_INEXACT     0x00000008	/*   inexact (precision)    */


#define IMCW_RC         0x00000003      /* Rounding Control Mask    */

#define IRC_NEAR        0x00000000      /*   near                   */
#define IRC_CHOP        0x00000001      /*   chop                   */
#define IRC_UP          0x00000002      /*   up                     */
#define IRC_DOWN        0x00000003      /*   down                   */


#define IMCW_SW		0x3E000000	/* Status Mask              */

#define ISW_INVALID     0x20000000      /*   invalid summary        */
#define ISW_OVERFLOW    0x10000000      /*   overflow               */
#define ISW_UNDERFLOW   0x08000000      /*   underflow              */
#define ISW_ZERODIVIDE  0x04000000      /*   zero divide            */
#define ISW_INEXACT     0x02000000      /*   inexact (precision)    */


#define IMCW_VX         0x01F80100      /* Invalid Cause Mask       */

#define IVX_SNAN	0x01000000	/*   SNaN                   */
#define IVX_ISI         0x00800000      /*   infinity - infinity    */
#define IVX_IDI         0x00400000      /*   infinity / infinity    */
#define IVX_ZDZ         0x00200000      /*   zero / zero            */
#define IVX_IMZ         0x00100000      /*   infinity * zero        */
#define IVX_VC          0x00080000      /*   inv flpt compare       */
#define IVX_CVI         0x00000100      /*   inv integer convert    */


/* Internal CW for transcendentals */

#define ICW             (IMCW_EM)

/* Internal CW Mask (non-status bits) */

#define IMCW           (0xffffffff & (~(IMCW_SW|IMCW_VX)))

#endif


#ifndef _LANGUAGE_ASSEMBLY

#define RETURN(fpcw,result) return _rstorfp(fpcw),(result)

#define RETURN_INEXACT1(op,arg1,res,cw) 		\
	if (cw & IEM_INEXACT) {				\
	    _rstorfp(cw);				\
	    return res; 				\
	}						\
	else {						\
	    return _except1(FP_P, op, arg1, res, cw);	\
	}


#define RETURN_INEXACT2(op,arg1,arg2,res,cw)		\
	if (cw & IEM_INEXACT) {				\
	    _rstorfp(cw);				\
	    return res; 				\
	}						\
	else {						\
	    return _except2(FP_P, op, arg1, arg2, res, cw);	\
	}

#ifdef _M_ALPHA

//
// Since fp32 is not compiled in IEEE exception mode perform Alpha NaN
// propagation in software to avoid hardware/kernel trap involvement.
//

extern double _nan2qnan(double);

#define _d_snan2(x,y)	_nan2qnan(y)
#define _s2qnan(x)	_nan2qnan(x)

#else
//handle NaN propagation
#define _d_snan2(x,y)	((x)+(y))
#define _s2qnan(x)	((x)+1.0)
#endif


#define _maskfp() _ctrlfp(ICW, IMCW)
#ifdef _ALPHA_
#define _rstorfp(cw) 0
#else
#define _rstorfp(cw) _ctrlfp(cw, IMCW)
#endif


#define ABS(x) ((x)<0 ? -(x) : (x) )


int _d_inttype(double);

#endif  /* _LANGUAGE_ASSEMBLY */

#define _D_NOINT 0
#define _D_ODD 1
#define _D_EVEN 2


// IEEE exceptions
#define FP_O	     0x01
#define FP_U	     0x02
#define FP_Z	     0x04
#define FP_I	     0x08
#define FP_P	     0x10

// An extra flag for matherr support
// Set together with FP_I from trig functions when the argument is too large
#define FP_TLOSS     0x20


#ifndef _LANGUAGE_ASSEMBLY
#ifdef B_END
#define SET_DBL(msw, lsw)     msw, lsw
#else
#define SET_DBL(msw, lsw)     lsw, msw
#endif
#endif  /* _LANGUAGE_ASSEMBLY */


// special types
#define T_PINF	1
#define T_NINF	2
#define T_QNAN	3
#define T_SNAN	4


// exponent adjustment for IEEE overflow/underflow exceptions
// used before passing the result to the trap handler

#define IEEE_ADJUST 1536

// QNAN values

#define INT_NAN 	(~0)

#define QNAN_SQRT	D_IND
#define QNAN_LOG	D_IND
#define QNAN_LOG10	D_IND
#define QNAN_POW	D_IND
#define QNAN_SINH	D_IND
#define QNAN_COSH	D_IND
#define QNAN_TANH	D_IND
#define QNAN_SIN1	D_IND
#define QNAN_SIN2	D_IND
#define QNAN_COS1	D_IND
#define QNAN_COS2	D_IND
#define QNAN_TAN1	D_IND
#define QNAN_TAN2	D_IND
#define QNAN_ACOS	D_IND
#define QNAN_ASIN	D_IND
#define QNAN_ATAN2	D_IND
#define QNAN_CEIL	D_IND
#define QNAN_FLOOR	D_IND
#define QNAN_MODF	D_IND
#define QNAN_LDEXP	D_IND
#define QNAN_FMOD	D_IND
#define QNAN_FREXP	D_IND


/*
 * Function prototypes
 */

#ifndef _LANGUAGE_ASSEMBLY

double _copysign(double x, double y);
double _set_exp(double x, int exp);
double _set_bexp(double x, int exp);
double _add_exp(double x, int exp);
double _frnd(double);
double _fsqrt(double);
/* Must have these declarations (or a suitable macro) or the C implementations
 * of a great many FP functions fail badly when there is an exception */
#ifndef	_except1
double _except1(int flags, int opcode, double arg, double res, unsigned int cw);
#endif
#ifndef	_except2
double _except2(int flags, int opcode, double arg1, double arg2, double res, unsigned int cw);
#endif
int _sptype(double);
int _get_exp(double);
double _decomp(double, int *);
int _powhlp(double x, double y, double * result);
extern unsigned int _fpstatus;
double _frnd(double);
double _exphlp(double, int *);
double _handle_qnan1(unsigned int op, double arg, unsigned int cw);
double _handle_qnan2(unsigned int op,double arg1,double arg2,unsigned int cw);
unsigned int _clhwfp(void);
unsigned int _setfpcw(unsigned int);
int _errcode(unsigned int flags);
void _set_errno(int matherrtype);
int _handle_exc(unsigned int flags, double * presult, unsigned int cw);
unsigned int _clrfp(void);
unsigned int _ctrlfp(unsigned int,unsigned int);
unsigned int _statfp(void);
void _set_statfp(unsigned int);

#endif  /* _LANGUAGE_ASSEMBLY */

#ifdef __cplusplus
}
#endif

#define _INC_TRANS
#endif	/* _INC_TRANS */