Commit | Line | Data |
---|---|---|
f24c459c JH |
1 | /* |
2 | * poly_2xm1.c | |
3 | * | |
4 | * Function to compute 2^x-1 by a polynomial approximation. | |
5 | * | |
6 | * | |
7 | * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond, | |
8 | * Vic 3163, Australia. | |
9 | * E-mail apm233m@vaxc.cc.monash.edu.au | |
10 | * All rights reserved. | |
11 | * | |
12 | * This copyright notice covers the redistribution and use of the | |
13 | * FPU emulator developed by W. Metzenthen. It covers only its use | |
14 | * in the 386BSD operating system. Any other use is not permitted | |
15 | * under this copyright. | |
16 | * | |
17 | * Redistribution and use in source and binary forms, with or without | |
18 | * modification, are permitted provided that the following conditions | |
19 | * are met: | |
20 | * 1. Redistributions of source code must retain the above copyright | |
21 | * notice, this list of conditions and the following disclaimer. | |
22 | * 2. Redistributions in binary form must include information specifying | |
23 | * that source code for the emulator is freely available and include | |
24 | * either: | |
25 | * a) an offer to provide the source code for a nominal distribution | |
26 | * fee, or | |
27 | * b) list at least two alternative methods whereby the source | |
28 | * can be obtained, e.g. a publically accessible bulletin board | |
29 | * and an anonymous ftp site from which the software can be | |
30 | * downloaded. | |
31 | * 3. All advertising materials specifically mentioning features or use of | |
32 | * this emulator must acknowledge that it was developed by W. Metzenthen. | |
33 | * 4. The name of W. Metzenthen may not be used to endorse or promote | |
34 | * products derived from this software without specific prior written | |
35 | * permission. | |
36 | * | |
37 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, | |
38 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY | |
39 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | |
40 | * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
41 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
42 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
43 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
44 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
45 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
46 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
47 | * | |
48 | */ | |
49 | ||
50 | #include "exception.h" | |
51 | #include "reg_constant.h" | |
52 | #include "fpu_emu.h" | |
53 | ||
54 | ||
55 | ||
56 | #define HIPOWER 13 | |
57 | static unsigned short lterms[HIPOWER][4] = | |
58 | { | |
59 | {0x79b5, 0xd1cf, 0x17f7, 0xb172}, | |
60 | {0x1b56, 0x058b, 0x7bff, 0x3d7f}, | |
61 | {0x8bb0, 0x8250, 0x846b, 0x0e35}, | |
62 | {0xbc65, 0xf747, 0x556d, 0x0276}, | |
63 | {0x17cb, 0x9e39, 0x61ff, 0x0057}, | |
64 | {0xe018, 0x9776, 0x1848, 0x000a}, | |
65 | {0x66f2, 0xff30, 0xffe5, 0x0000}, | |
66 | {0x682f, 0xffb6, 0x162b, 0x0000}, | |
67 | {0xb7ca, 0x2956, 0x01b5, 0x0000}, | |
68 | {0xcd3e, 0x4817, 0x001e, 0x0000}, | |
69 | {0xb7e2, 0xecbe, 0x0001, 0x0000}, | |
70 | {0x0ed5, 0x1a27, 0x0000, 0x0000}, | |
71 | {0x101d, 0x0222, 0x0000, 0x0000}, | |
72 | }; | |
73 | ||
74 | ||
75 | /*--- poly_2xm1() -----------------------------------------------------------+ | |
76 | | | | |
77 | +---------------------------------------------------------------------------*/ | |
78 | int | |
79 | poly_2xm1(FPU_REG * arg, FPU_REG * result) | |
80 | { | |
81 | short exponent; | |
82 | long long Xll; | |
83 | FPU_REG accum; | |
84 | ||
85 | ||
86 | exponent = arg->exp - EXP_BIAS; | |
87 | ||
88 | if (arg->tag == TW_Zero) { | |
89 | /* Return 0.0 */ | |
90 | reg_move(&CONST_Z, result); | |
91 | return 0; | |
92 | } | |
93 | if (exponent >= 0) { /* Can't hack a number >= 1.0 */ | |
94 | arith_invalid(result); /* Number too large */ | |
95 | return 1; | |
96 | } | |
97 | if (arg->sign != SIGN_POS) { /* Can't hack a number < 0.0 */ | |
98 | arith_invalid(result); /* Number negative */ | |
99 | return 1; | |
100 | } | |
101 | if (exponent < -64) { | |
102 | reg_move(&CONST_LN2, result); | |
103 | return 0; | |
104 | } | |
105 | *(unsigned *) &Xll = arg->sigl; | |
106 | *(((unsigned *) &Xll) + 1) = arg->sigh; | |
107 | if (exponent < -1) { | |
108 | /* shift the argument right by the required places */ | |
109 | if (shrx(&Xll, -1 - exponent) >= (unsigned)0x80000000) | |
110 | Xll++; /* round up */ | |
111 | } | |
112 | *(short *) &(accum.sign) = 0; /* will be a valid positive nr with | |
113 | * expon = 0 */ | |
114 | accum.exp = 0; | |
115 | ||
116 | /* Do the basic fixed point polynomial evaluation */ | |
117 | polynomial((unsigned *) &accum.sigl, (unsigned *) &Xll, lterms, HIPOWER - 1); | |
118 | ||
119 | /* Convert to 64 bit signed-compatible */ | |
120 | accum.exp += EXP_BIAS - 1; | |
121 | ||
122 | reg_move(&accum, result); | |
123 | ||
124 | normalize(result); | |
125 | ||
126 | return 0; | |
127 | ||
128 | } |