source: mainline/softfloat/generic/mul.c@ 1266543

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

32 bit float division added.
Some small bugs fixed.
Code cleanup.

  • Property mode set to 100644
File size: 8.3 KB
RevLine 
[b5440cf]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>
[12c6f2d]30#include<mul.h>
[cf4a823]31#include<comparison.h>
[b5440cf]32
[3af72dc]33/** Multiply two 32 bit float numbers
34 *
35 */
36float32 mulFloat32(float32 a, float32 b)
37{
38 float32 result;
[1266543]39 __u64 frac1, frac2;
[3af72dc]40 __s32 exp;
41
42 result.parts.sign = a.parts.sign ^ b.parts.sign;
43
[bff16dd]44 if (isFloat32NaN(a) || isFloat32NaN(b) ) {
[3af72dc]45 /* TODO: fix SigNaNs */
46 if (isFloat32SigNaN(a)) {
[1266543]47 result.parts.fraction = a.parts.fraction;
[3af72dc]48 result.parts.exp = a.parts.exp;
49 return result;
50 };
51 if (isFloat32SigNaN(b)) { /* TODO: fix SigNaN */
[1266543]52 result.parts.fraction = b.parts.fraction;
[3af72dc]53 result.parts.exp = b.parts.exp;
54 return result;
55 };
56 /* set NaN as result */
[bff16dd]57 result.binary = FLOAT32_NAN;
[3af72dc]58 return result;
59 };
60
61 if (isFloat32Infinity(a)) {
62 if (isFloat32Zero(b)) {
63 /* FIXME: zero * infinity */
[bff16dd]64 result.binary = FLOAT32_NAN;
[3af72dc]65 return result;
66 }
[1266543]67 result.parts.fraction = a.parts.fraction;
[3af72dc]68 result.parts.exp = a.parts.exp;
69 return result;
70 }
71
72 if (isFloat32Infinity(b)) {
73 if (isFloat32Zero(a)) {
74 /* FIXME: zero * infinity */
[bff16dd]75 result.binary = FLOAT32_NAN;
[3af72dc]76 return result;
77 }
[1266543]78 result.parts.fraction = b.parts.fraction;
[3af72dc]79 result.parts.exp = b.parts.exp;
80 return result;
81 }
82
83 /* exp is signed so we can easy detect underflow */
84 exp = a.parts.exp + b.parts.exp;
85 exp -= FLOAT32_BIAS;
86
[bff16dd]87 if (exp >= FLOAT32_MAX_EXPONENT) {
[3af72dc]88 /* FIXME: overflow */
89 /* set infinity as result */
[bff16dd]90 result.binary = FLOAT32_INF;
91 result.parts.sign = a.parts.sign ^ b.parts.sign;
[3af72dc]92 return result;
93 };
94
95 if (exp < 0) {
96 /* FIXME: underflow */
97 /* return signed zero */
[1266543]98 result.parts.fraction = 0x0;
[3af72dc]99 result.parts.exp = 0x0;
100 return result;
101 };
102
[1266543]103 frac1 = a.parts.fraction;
[bff16dd]104 if (a.parts.exp > 0) {
[1266543]105 frac1 |= FLOAT32_HIDDEN_BIT_MASK;
[3af72dc]106 } else {
107 ++exp;
108 };
109
[1266543]110 frac2 = b.parts.fraction;
[bff16dd]111
112 if (b.parts.exp > 0) {
[1266543]113 frac2 |= FLOAT32_HIDDEN_BIT_MASK;
[3af72dc]114 } else {
115 ++exp;
116 };
117
[1266543]118 frac1 <<= 1; /* one bit space for rounding */
[3af72dc]119
[1266543]120 frac1 = frac1 * frac2;
[3af72dc]121/* round and return */
122
[1266543]123 while ((exp < FLOAT32_MAX_EXPONENT) && (frac1 >= ( 1 << (FLOAT32_FRACTION_SIZE + 2)))) {
124 /* 23 bits of fraction + one more for hidden bit (all shifted 1 bit left)*/
[3af72dc]125 ++exp;
[1266543]126 frac1 >>= 1;
[3af72dc]127 };
128
129 /* rounding */
[1266543]130 /* ++frac1; FIXME: not works - without it is ok */
131 frac1 >>= 1; /* shift off rounding space */
[3af72dc]132
[1266543]133 if ((exp < FLOAT32_MAX_EXPONENT) && (frac1 >= (1 << (FLOAT32_FRACTION_SIZE + 1)))) {
[3af72dc]134 ++exp;
[1266543]135 frac1 >>= 1;
[3af72dc]136 };
137
[bff16dd]138 if (exp >= FLOAT32_MAX_EXPONENT ) {
[3af72dc]139 /* TODO: fix overflow */
140 /* return infinity*/
[bff16dd]141 result.parts.exp = FLOAT32_MAX_EXPONENT;
[1266543]142 result.parts.fraction = 0x0;
[3af72dc]143 return result;
144 }
145
[1266543]146 exp -= FLOAT32_FRACTION_SIZE;
[3af72dc]147
[1266543]148 if (exp <= FLOAT32_FRACTION_SIZE) {
[3af72dc]149 /* denormalized number */
[1266543]150 frac1 >>= 1; /* denormalize */
151 while ((frac1 > 0) && (exp < 0)) {
152 frac1 >>= 1;
[3af72dc]153 ++exp;
154 };
[1266543]155 if (frac1 == 0) {
[3af72dc]156 /* FIXME : underflow */
157 result.parts.exp = 0;
[1266543]158 result.parts.fraction = 0;
[3af72dc]159 return result;
160 };
161 };
162 result.parts.exp = exp;
[1266543]163 result.parts.fraction = frac1 & ( (1 << FLOAT32_FRACTION_SIZE) - 1);
[bff16dd]164
165 return result;
166
167}
168
169/** Multiply two 64 bit float numbers
170 *
171 */
172float64 mulFloat64(float64 a, float64 b)
173{
174 float64 result;
[1266543]175 __u64 frac1, frac2;
[bff16dd]176 __s32 exp;
177
178 result.parts.sign = a.parts.sign ^ b.parts.sign;
179
180 if (isFloat64NaN(a) || isFloat64NaN(b) ) {
181 /* TODO: fix SigNaNs */
182 if (isFloat64SigNaN(a)) {
[1266543]183 result.parts.fraction = a.parts.fraction;
[bff16dd]184 result.parts.exp = a.parts.exp;
185 return result;
186 };
187 if (isFloat64SigNaN(b)) { /* TODO: fix SigNaN */
[1266543]188 result.parts.fraction = b.parts.fraction;
[bff16dd]189 result.parts.exp = b.parts.exp;
190 return result;
191 };
192 /* set NaN as result */
193 result.binary = FLOAT64_NAN;
194 return result;
195 };
196
197 if (isFloat64Infinity(a)) {
198 if (isFloat64Zero(b)) {
199 /* FIXME: zero * infinity */
200 result.binary = FLOAT64_NAN;
201 return result;
202 }
[1266543]203 result.parts.fraction = a.parts.fraction;
[bff16dd]204 result.parts.exp = a.parts.exp;
205 return result;
206 }
207
208 if (isFloat64Infinity(b)) {
209 if (isFloat64Zero(a)) {
210 /* FIXME: zero * infinity */
211 result.binary = FLOAT64_NAN;
212 return result;
213 }
[1266543]214 result.parts.fraction = b.parts.fraction;
[bff16dd]215 result.parts.exp = b.parts.exp;
216 return result;
217 }
218
219 /* exp is signed so we can easy detect underflow */
220 exp = a.parts.exp + b.parts.exp;
221 exp -= FLOAT64_BIAS;
222
223 if (exp >= FLOAT64_MAX_EXPONENT) {
224 /* FIXME: overflow */
225 /* set infinity as result */
226 result.binary = FLOAT64_INF;
227 result.parts.sign = a.parts.sign ^ b.parts.sign;
228 return result;
229 };
230
231 if (exp < 0) {
232 /* FIXME: underflow */
233 /* return signed zero */
[1266543]234 result.parts.fraction = 0x0;
[bff16dd]235 result.parts.exp = 0x0;
236 return result;
237 };
238
[1266543]239 frac1 = a.parts.fraction;
[bff16dd]240 if (a.parts.exp > 0) {
[1266543]241 frac1 |= FLOAT64_HIDDEN_BIT_MASK;
[bff16dd]242 } else {
243 ++exp;
244 };
245
[1266543]246 frac2 = b.parts.fraction;
[bff16dd]247
248 if (b.parts.exp > 0) {
[1266543]249 frac2 |= FLOAT64_HIDDEN_BIT_MASK;
[bff16dd]250 } else {
251 ++exp;
252 };
253
[1266543]254 frac1 <<= 1; /* one bit space for rounding */
[bff16dd]255
[1266543]256 mul64integers(frac1, frac2, &frac1, &frac2);
[bff16dd]257
258/* round and return */
[1266543]259 /* FIXME: ugly soulution is to shift whole frac2 >> as in 32bit version
[bff16dd]260 * Here is is more slower because we have to shift two numbers with carry
261 * Better is find first nonzero bit and make only one shift
262 * Third version is to shift both numbers a bit to right and result will be then
263 * placed in higher part of result. Then lower part will be good only for rounding.
264 */
265
[1266543]266 while ((exp < FLOAT64_MAX_EXPONENT) && (frac2 > 0 )) {
267 frac1 >>= 1;
268 frac1 &= ((frac2 & 0x1) << 63);
269 frac2 >>= 1;
[bff16dd]270 ++exp;
271 }
272
[1266543]273 while ((exp < FLOAT64_MAX_EXPONENT) && (frac1 >= ( (__u64)1 << (FLOAT64_FRACTION_SIZE + 2)))) {
[bff16dd]274 ++exp;
[1266543]275 frac1 >>= 1;
[bff16dd]276 };
277
278 /* rounding */
[1266543]279 /* ++frac1; FIXME: not works - without it is ok */
280 frac1 >>= 1; /* shift off rounding space */
[bff16dd]281
[1266543]282 if ((exp < FLOAT64_MAX_EXPONENT) && (frac1 >= ((__u64)1 << (FLOAT64_FRACTION_SIZE + 1)))) {
[bff16dd]283 ++exp;
[1266543]284 frac1 >>= 1;
[bff16dd]285 };
286
287 if (exp >= FLOAT64_MAX_EXPONENT ) {
288 /* TODO: fix overflow */
289 /* return infinity*/
290 result.parts.exp = FLOAT64_MAX_EXPONENT;
[1266543]291 result.parts.fraction = 0x0;
[bff16dd]292 return result;
293 }
294
[1266543]295 exp -= FLOAT64_FRACTION_SIZE;
[bff16dd]296
[1266543]297 if (exp <= FLOAT64_FRACTION_SIZE) {
[bff16dd]298 /* denormalized number */
[1266543]299 frac1 >>= 1; /* denormalize */
300 while ((frac1 > 0) && (exp < 0)) {
301 frac1 >>= 1;
[bff16dd]302 ++exp;
303 };
[1266543]304 if (frac1 == 0) {
[bff16dd]305 /* FIXME : underflow */
306 result.parts.exp = 0;
[1266543]307 result.parts.fraction = 0;
[bff16dd]308 return result;
309 };
310 };
311 result.parts.exp = exp;
[1266543]312 result.parts.fraction = frac1 & ( ((__u64)1 << FLOAT64_FRACTION_SIZE) - 1);
[3af72dc]313
314 return result;
315
[12c6f2d]316}
317
[bff16dd]318/** Multiply two 64 bit numbers and return result in two parts
319 * @param a first operand
320 * @param b second operand
321 * @param lo lower part from result
322 * @param hi higher part of result
323 */
324void mul64integers(__u64 a,__u64 b, __u64 *lo, __u64 *hi)
325{
326 __u64 low, high, middle1, middle2;
327 __u32 alow, blow;
328
329 alow = a & 0xFFFFFFFF;
330 blow = b & 0xFFFFFFFF;
331
332 a <<= 32;
333 b <<= 32;
334
335 low = (__u64)alow * blow;
336 middle1 = a * blow;
337 middle2 = alow * b;
338 high = a * b;
339
340 middle1 += middle2;
[1266543]341 high += ((__u64)(middle1 < middle2) << 32) + (middle1 >> 32);
342 middle1 <<= 32;
[bff16dd]343 low += middle1;
344 high += (low < middle1);
345 *lo = low;
346 *hi = high;
347 return;
348}
[3af72dc]349
350
Note: See TracBrowser for help on using the repository browser.