source: mainline/softfloat/generic/sub.c@ aa59fa0

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since aa59fa0 was aa59fa0, checked in by Josef Cejka <malyzelenyhnus@…>, 19 years ago

SoftFloat integrated into HelenOS uspace.

  • Property mode set to 100644
File size: 6.2 KB
Line 
1/*
2 * Copyright (C) 2005 Josef Cejka
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
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include<sftypes.h>
30#include<sub.h>
31#include<comparison.h>
32
33/** Subtract two float32 numbers with same signs
34 */
35float32 subFloat32(float32 a, float32 b)
36{
37 int expdiff;
38 uint32_t exp1, exp2, frac1, frac2;
39 float32 result;
40
41 result.f = 0;
42
43 expdiff = a.parts.exp - b.parts.exp;
44 if ((expdiff < 0 ) || ((expdiff == 0) && (a.parts.fraction < b.parts.fraction))) {
45 if (isFloat32NaN(b)) {
46 /* TODO: fix SigNaN */
47 if (isFloat32SigNaN(b)) {
48 };
49 return b;
50 };
51
52 if (b.parts.exp == FLOAT32_MAX_EXPONENT) {
53 b.parts.sign = !b.parts.sign; /* num -(+-inf) = -+inf */
54 return b;
55 }
56
57 result.parts.sign = !a.parts.sign;
58
59 frac1 = b.parts.fraction;
60 exp1 = b.parts.exp;
61 frac2 = a.parts.fraction;
62 exp2 = a.parts.exp;
63 expdiff *= -1;
64 } else {
65 if (isFloat32NaN(a)) {
66 /* TODO: fix SigNaN */
67 if (isFloat32SigNaN(a) || isFloat32SigNaN(b)) {
68 };
69 return a;
70 };
71
72 if (a.parts.exp == FLOAT32_MAX_EXPONENT) {
73 if (b.parts.exp == FLOAT32_MAX_EXPONENT) {
74 /* inf - inf => nan */
75 /* TODO: fix exception */
76 result.binary = FLOAT32_NAN;
77 return result;
78 };
79 return a;
80 }
81
82 result.parts.sign = a.parts.sign;
83
84 frac1 = a.parts.fraction;
85 exp1 = a.parts.exp;
86 frac2 = b.parts.fraction;
87 exp2 = b.parts.exp;
88 };
89
90 if (exp1 == 0) {
91 /* both are denormalized */
92 result.parts.fraction = frac1-frac2;
93 if (result.parts.fraction > frac1) {
94 /* TODO: underflow exception */
95 return result;
96 };
97 result.parts.exp = 0;
98 return result;
99 };
100
101 /* add hidden bit */
102 frac1 |= FLOAT32_HIDDEN_BIT_MASK;
103
104 if (exp2 == 0) {
105 /* denormalized */
106 --expdiff;
107 } else {
108 /* normalized */
109 frac2 |= FLOAT32_HIDDEN_BIT_MASK;
110 };
111
112 /* create some space for rounding */
113 frac1 <<= 6;
114 frac2 <<= 6;
115
116 if (expdiff > FLOAT32_FRACTION_SIZE + 1) {
117 goto done;
118 };
119
120 frac1 = frac1 - (frac2 >> expdiff);
121done:
122 /* TODO: find first nonzero digit and shift result and detect possibly underflow */
123 while ((exp1 > 0) && (!(frac1 & (FLOAT32_HIDDEN_BIT_MASK << 6 )))) {
124 --exp1;
125 frac1 <<= 1;
126 /* TODO: fix underflow - frac1 == 0 does not necessary means underflow... */
127 };
128
129 /* rounding - if first bit after fraction is set then round up */
130 frac1 += 0x20;
131
132 if (frac1 & (FLOAT32_HIDDEN_BIT_MASK << 7)) {
133 ++exp1;
134 frac1 >>= 1;
135 };
136
137 /*Clear hidden bit and shift */
138 result.parts.fraction = ((frac1 >> 6) & (~FLOAT32_HIDDEN_BIT_MASK));
139 result.parts.exp = exp1;
140
141 return result;
142}
143
144/** Subtract two float64 numbers with same signs
145 */
146float64 subFloat64(float64 a, float64 b)
147{
148 int expdiff;
149 uint32_t exp1, exp2;
150 uint64_t frac1, frac2;
151 float64 result;
152
153 result.d = 0;
154
155 expdiff = a.parts.exp - b.parts.exp;
156 if ((expdiff < 0 ) || ((expdiff == 0) && (a.parts.fraction < b.parts.fraction))) {
157 if (isFloat64NaN(b)) {
158 /* TODO: fix SigNaN */
159 if (isFloat64SigNaN(b)) {
160 };
161 return b;
162 };
163
164 if (b.parts.exp == FLOAT64_MAX_EXPONENT) {
165 b.parts.sign = !b.parts.sign; /* num -(+-inf) = -+inf */
166 return b;
167 }
168
169 result.parts.sign = !a.parts.sign;
170
171 frac1 = b.parts.fraction;
172 exp1 = b.parts.exp;
173 frac2 = a.parts.fraction;
174 exp2 = a.parts.exp;
175 expdiff *= -1;
176 } else {
177 if (isFloat64NaN(a)) {
178 /* TODO: fix SigNaN */
179 if (isFloat64SigNaN(a) || isFloat64SigNaN(b)) {
180 };
181 return a;
182 };
183
184 if (a.parts.exp == FLOAT64_MAX_EXPONENT) {
185 if (b.parts.exp == FLOAT64_MAX_EXPONENT) {
186 /* inf - inf => nan */
187 /* TODO: fix exception */
188 result.binary = FLOAT64_NAN;
189 return result;
190 };
191 return a;
192 }
193
194 result.parts.sign = a.parts.sign;
195
196 frac1 = a.parts.fraction;
197 exp1 = a.parts.exp;
198 frac2 = b.parts.fraction;
199 exp2 = b.parts.exp;
200 };
201
202 if (exp1 == 0) {
203 /* both are denormalized */
204 result.parts.fraction = frac1 - frac2;
205 if (result.parts.fraction > frac1) {
206 /* TODO: underflow exception */
207 return result;
208 };
209 result.parts.exp = 0;
210 return result;
211 };
212
213 /* add hidden bit */
214 frac1 |= FLOAT64_HIDDEN_BIT_MASK;
215
216 if (exp2 == 0) {
217 /* denormalized */
218 --expdiff;
219 } else {
220 /* normalized */
221 frac2 |= FLOAT64_HIDDEN_BIT_MASK;
222 };
223
224 /* create some space for rounding */
225 frac1 <<= 6;
226 frac2 <<= 6;
227
228 if (expdiff > FLOAT64_FRACTION_SIZE + 1) {
229 goto done;
230 };
231
232 frac1 = frac1 - (frac2 >> expdiff);
233done:
234 /* TODO: find first nonzero digit and shift result and detect possibly underflow */
235 while ((exp1 > 0) && (!(frac1 & (FLOAT64_HIDDEN_BIT_MASK << 6 )))) {
236 --exp1;
237 frac1 <<= 1;
238 /* TODO: fix underflow - frac1 == 0 does not necessary means underflow... */
239 };
240
241 /* rounding - if first bit after fraction is set then round up */
242 frac1 += 0x20;
243
244 if (frac1 & (FLOAT64_HIDDEN_BIT_MASK << 7)) {
245 ++exp1;
246 frac1 >>= 1;
247 };
248
249 /*Clear hidden bit and shift */
250 result.parts.fraction = ((frac1 >> 6) & (~FLOAT64_HIDDEN_BIT_MASK));
251 result.parts.exp = exp1;
252
253 return result;
254}
255
Note: See TracBrowser for help on using the repository browser.