This source file includes following definitions.
- poly_sine
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #include "exception.h"
15 #include "reg_constant.h"
16 #include "fpu_emu.h"
17 #include "control_w.h"
18
19
20 #define HIPOWER 5
21 static unsigned short lterms[HIPOWER][4] =
22 {
23 { 0x846a, 0x42d1, 0xb544, 0x921f},
24 { 0xe110, 0x75aa, 0xbc67, 0x1466},
25 { 0x503d, 0xa43f, 0x83c1, 0x000a},
26 { 0x8f9d, 0x7a19, 0x00f4, 0x0000},
27 { 0xda03, 0x06aa, 0x0000, 0x0000},
28 };
29
30 static unsigned short negterms[HIPOWER][4] =
31 {
32 { 0x95ed, 0x2df2, 0xe731, 0xa55d},
33 { 0xd159, 0xe62b, 0xd2cc, 0x0132},
34 { 0x6342, 0xe9fb, 0x3c60, 0x0000},
35 { 0x6256, 0xdf5a, 0x0002, 0x0000},
36 { 0xf279, 0x000b, 0x0000, 0x0000},
37 };
38
39
40
41
42
43 void poly_sine(FPU_REG *arg, FPU_REG *result)
44 {
45 short exponent;
46 FPU_REG Xx, Xx2, Xx4, accum, negaccum;
47
48
49 exponent = arg->exp - EXP_BIAS;
50
51 if ( arg->tag == TW_Zero )
52 {
53
54 reg_move(&CONST_Z, result);
55 return;
56 }
57
58 #ifdef PARANOID
59 if ( arg->sign != 0 )
60 {
61 EXCEPTION(EX_Invalid);
62 reg_move(&CONST_QNaN, result);
63 return;
64 }
65
66 if ( exponent >= 0 )
67 {
68 if ( (exponent == 0) && (arg->sigl == 0) && (arg->sigh == 0x80000000) )
69 {
70 reg_move(&CONST_1, result);
71 return;
72 }
73 EXCEPTION(EX_Invalid);
74 reg_move(&CONST_QNaN, result);
75 return;
76 }
77 #endif PARANOID
78
79 Xx.sigl = arg->sigl;
80 Xx.sigh = arg->sigh;
81 if ( exponent < -1 )
82 {
83
84 if ( shrx(&(Xx.sigl), -1-exponent) >= 0x80000000U )
85 (*((long long *)(&(Xx.sigl))))++;
86 }
87
88 mul64((long long *)&(Xx.sigl), (long long *)&(Xx.sigl),
89 (long long *)&(Xx2.sigl));
90 mul64((long long *)&(Xx2.sigl), (long long *)&(Xx2.sigl),
91 (long long *)&(Xx4.sigl));
92
93
94 *(short *)&(accum.sign) = 0;
95 accum.exp = 0;
96
97
98 polynomial(&(accum.sigl), &(Xx4.sigl), lterms, HIPOWER-1);
99
100
101 *(short *)&(negaccum.sign) = 0;
102 negaccum.exp = 0;
103
104
105 polynomial(&(negaccum.sigl), &(Xx4.sigl), negterms, HIPOWER-1);
106 mul64((long long *)&(Xx2.sigl), (long long *)&(negaccum.sigl),
107 (long long *)&(negaccum.sigl));
108
109
110 *((long long *)(&(accum.sigl))) -= *((long long *)(&(negaccum.sigl)));
111
112
113 accum.exp = EXP_BIAS - 1 + accum.exp;
114
115 *(short *)&(result->sign) = *(short *)&(accum.sign);
116 result->exp = accum.exp;
117 result->sigl = accum.sigl;
118 result->sigh = accum.sigh;
119
120 normalize(result);
121
122 reg_mul(result, arg, result, FULL_PRECISION);
123 reg_u_add(result, arg, result, FULL_PRECISION);
124
125
126 if ( result->exp >= EXP_BIAS )
127 {
128 if ( (result->exp > EXP_BIAS)
129 || (result->sigl > 1)
130 || (result->sigh != 0x80000000)
131 )
132 {
133 #ifdef DEBUGGING
134 RE_ENTRANT_CHECK_OFF
135 printk("\nEXP=%d, MS=%08x, LS=%08x\n", result->exp,
136 result->sigh, result->sigl);
137 RE_ENTRANT_CHECK_ON
138 #endif DEBUGGING
139 EXCEPTION(EX_INTERNAL|0x103);
140 }
141
142 #ifdef DEBUGGING
143 RE_ENTRANT_CHECK_OFF
144 printk("\n***CORRECTING ILLEGAL RESULT*** in poly_sin() computation\n");
145 printk("EXP=%d, MS=%08x, LS=%08x\n", result->exp,
146 result->sigh, result->sigl);
147 RE_ENTRANT_CHECK_ON
148 #endif DEBUGGING
149
150 result->sigl = 0;
151 }
152 }