source: mainline/uspace/lib/softfloat/generic/mul.c@ 9a6034a

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 9a6034a was 750636a, checked in by Martin Decky <martin@…>, 14 years ago

softfloat: slightly improve coding style (no change in functionality)

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