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

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

SoftFloat integrated into HelenOS uspace.

  • Property mode set to 100644
File size: 6.7 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>
[e979fea]32#include<common.h>
[b5440cf]33
[3af72dc]34/** Multiply two 32 bit float numbers
35 *
36 */
37float32 mulFloat32(float32 a, float32 b)
38{
39 float32 result;
[aa59fa0]40 uint64_t frac1, frac2;
41 int32_t exp;
[3af72dc]42
43 result.parts.sign = a.parts.sign ^ b.parts.sign;
44
[bff16dd]45 if (isFloat32NaN(a) || isFloat32NaN(b) ) {
[3af72dc]46 /* TODO: fix SigNaNs */
47 if (isFloat32SigNaN(a)) {
[1266543]48 result.parts.fraction = a.parts.fraction;
[3af72dc]49 result.parts.exp = a.parts.exp;
50 return result;
51 };
52 if (isFloat32SigNaN(b)) { /* TODO: fix SigNaN */
[1266543]53 result.parts.fraction = b.parts.fraction;
[3af72dc]54 result.parts.exp = b.parts.exp;
55 return result;
56 };
57 /* set NaN as result */
[bff16dd]58 result.binary = FLOAT32_NAN;
[3af72dc]59 return result;
60 };
61
62 if (isFloat32Infinity(a)) {
63 if (isFloat32Zero(b)) {
64 /* FIXME: zero * infinity */
[bff16dd]65 result.binary = FLOAT32_NAN;
[3af72dc]66 return result;
67 }
[1266543]68 result.parts.fraction = a.parts.fraction;
[3af72dc]69 result.parts.exp = a.parts.exp;
70 return result;
71 }
72
73 if (isFloat32Infinity(b)) {
74 if (isFloat32Zero(a)) {
75 /* FIXME: zero * infinity */
[bff16dd]76 result.binary = FLOAT32_NAN;
[3af72dc]77 return result;
78 }
[1266543]79 result.parts.fraction = b.parts.fraction;
[3af72dc]80 result.parts.exp = b.parts.exp;
81 return result;
82 }
83
84 /* exp is signed so we can easy detect underflow */
85 exp = a.parts.exp + b.parts.exp;
86 exp -= FLOAT32_BIAS;
87
[bff16dd]88 if (exp >= FLOAT32_MAX_EXPONENT) {
[3af72dc]89 /* FIXME: overflow */
90 /* set infinity as result */
[bff16dd]91 result.binary = FLOAT32_INF;
92 result.parts.sign = a.parts.sign ^ b.parts.sign;
[3af72dc]93 return result;
94 };
95
96 if (exp < 0) {
97 /* FIXME: underflow */
98 /* return signed zero */
[1266543]99 result.parts.fraction = 0x0;
[3af72dc]100 result.parts.exp = 0x0;
101 return result;
102 };
103
[1266543]104 frac1 = a.parts.fraction;
[bff16dd]105 if (a.parts.exp > 0) {
[1266543]106 frac1 |= FLOAT32_HIDDEN_BIT_MASK;
[3af72dc]107 } else {
108 ++exp;
109 };
110
[1266543]111 frac2 = b.parts.fraction;
[bff16dd]112
113 if (b.parts.exp > 0) {
[1266543]114 frac2 |= FLOAT32_HIDDEN_BIT_MASK;
[3af72dc]115 } else {
116 ++exp;
117 };
118
[1266543]119 frac1 <<= 1; /* one bit space for rounding */
[3af72dc]120
[1266543]121 frac1 = frac1 * frac2;
[3af72dc]122/* round and return */
123
[1266543]124 while ((exp < FLOAT32_MAX_EXPONENT) && (frac1 >= ( 1 << (FLOAT32_FRACTION_SIZE + 2)))) {
125 /* 23 bits of fraction + one more for hidden bit (all shifted 1 bit left)*/
[3af72dc]126 ++exp;
[1266543]127 frac1 >>= 1;
[3af72dc]128 };
129
130 /* rounding */
[1266543]131 /* ++frac1; FIXME: not works - without it is ok */
132 frac1 >>= 1; /* shift off rounding space */
[3af72dc]133
[1266543]134 if ((exp < FLOAT32_MAX_EXPONENT) && (frac1 >= (1 << (FLOAT32_FRACTION_SIZE + 1)))) {
[3af72dc]135 ++exp;
[1266543]136 frac1 >>= 1;
[3af72dc]137 };
138
[bff16dd]139 if (exp >= FLOAT32_MAX_EXPONENT ) {
[3af72dc]140 /* TODO: fix overflow */
141 /* return infinity*/
[bff16dd]142 result.parts.exp = FLOAT32_MAX_EXPONENT;
[1266543]143 result.parts.fraction = 0x0;
[3af72dc]144 return result;
145 }
146
[1266543]147 exp -= FLOAT32_FRACTION_SIZE;
[3af72dc]148
[1266543]149 if (exp <= FLOAT32_FRACTION_SIZE) {
[3af72dc]150 /* denormalized number */
[1266543]151 frac1 >>= 1; /* denormalize */
152 while ((frac1 > 0) && (exp < 0)) {
153 frac1 >>= 1;
[3af72dc]154 ++exp;
155 };
[1266543]156 if (frac1 == 0) {
[3af72dc]157 /* FIXME : underflow */
158 result.parts.exp = 0;
[1266543]159 result.parts.fraction = 0;
[3af72dc]160 return result;
161 };
162 };
163 result.parts.exp = exp;
[1266543]164 result.parts.fraction = frac1 & ( (1 << FLOAT32_FRACTION_SIZE) - 1);
[bff16dd]165
166 return result;
167
168}
169
170/** Multiply two 64 bit float numbers
171 *
172 */
173float64 mulFloat64(float64 a, float64 b)
174{
175 float64 result;
[aa59fa0]176 uint64_t frac1, frac2;
177 int32_t exp;
[bff16dd]178
179 result.parts.sign = a.parts.sign ^ b.parts.sign;
180
181 if (isFloat64NaN(a) || isFloat64NaN(b) ) {
182 /* TODO: fix SigNaNs */
183 if (isFloat64SigNaN(a)) {
[1266543]184 result.parts.fraction = a.parts.fraction;
[bff16dd]185 result.parts.exp = a.parts.exp;
186 return result;
187 };
188 if (isFloat64SigNaN(b)) { /* TODO: fix SigNaN */
[1266543]189 result.parts.fraction = b.parts.fraction;
[bff16dd]190 result.parts.exp = b.parts.exp;
191 return result;
192 };
193 /* set NaN as result */
194 result.binary = FLOAT64_NAN;
195 return result;
196 };
197
198 if (isFloat64Infinity(a)) {
199 if (isFloat64Zero(b)) {
200 /* FIXME: zero * infinity */
201 result.binary = FLOAT64_NAN;
202 return result;
203 }
[1266543]204 result.parts.fraction = a.parts.fraction;
[bff16dd]205 result.parts.exp = a.parts.exp;
206 return result;
207 }
208
209 if (isFloat64Infinity(b)) {
210 if (isFloat64Zero(a)) {
211 /* FIXME: zero * infinity */
212 result.binary = FLOAT64_NAN;
213 return result;
214 }
[1266543]215 result.parts.fraction = b.parts.fraction;
[bff16dd]216 result.parts.exp = b.parts.exp;
217 return result;
218 }
219
220 /* exp is signed so we can easy detect underflow */
[e979fea]221 exp = a.parts.exp + b.parts.exp - FLOAT64_BIAS;
[bff16dd]222
[1266543]223 frac1 = a.parts.fraction;
[e979fea]224
[bff16dd]225 if (a.parts.exp > 0) {
[1266543]226 frac1 |= FLOAT64_HIDDEN_BIT_MASK;
[bff16dd]227 } else {
228 ++exp;
229 };
230
[1266543]231 frac2 = b.parts.fraction;
[bff16dd]232
233 if (b.parts.exp > 0) {
[1266543]234 frac2 |= FLOAT64_HIDDEN_BIT_MASK;
[bff16dd]235 } else {
236 ++exp;
237 };
238
[e979fea]239 frac1 <<= (64 - FLOAT64_FRACTION_SIZE - 1);
240 frac2 <<= (64 - FLOAT64_FRACTION_SIZE - 2);
[bff16dd]241
[1266543]242 mul64integers(frac1, frac2, &frac1, &frac2);
[bff16dd]243
[e979fea]244 frac2 |= (frac1 != 0);
245 if (frac2 & (0x1ll << 62)) {
246 frac2 <<= 1;
247 exp--;
[bff16dd]248 }
249
[e979fea]250 result = finishFloat64(exp, frac2, result.parts.sign);
251 return result;
[12c6f2d]252}
253
[bff16dd]254/** Multiply two 64 bit numbers and return result in two parts
255 * @param a first operand
256 * @param b second operand
257 * @param lo lower part from result
258 * @param hi higher part of result
259 */
[aa59fa0]260void mul64integers(uint64_t a,uint64_t b, uint64_t *lo, uint64_t *hi)
[bff16dd]261{
[aa59fa0]262 uint64_t low, high, middle1, middle2;
263 uint32_t alow, blow;
[e979fea]264
[bff16dd]265 alow = a & 0xFFFFFFFF;
266 blow = b & 0xFFFFFFFF;
267
[e6a40ac]268 a >>= 32;
269 b >>= 32;
[bff16dd]270
[aa59fa0]271 low = ((uint64_t)alow) * blow;
[bff16dd]272 middle1 = a * blow;
273 middle2 = alow * b;
274 high = a * b;
275
276 middle1 += middle2;
[aa59fa0]277 high += (((uint64_t)(middle1 < middle2)) << 32) + (middle1 >> 32);
[1266543]278 middle1 <<= 32;
[bff16dd]279 low += middle1;
280 high += (low < middle1);
281 *lo = low;
282 *hi = high;
[e6a40ac]283
[bff16dd]284 return;
285}
[3af72dc]286
287
Note: See TracBrowser for help on using the repository browser.