source: mainline/uspace/softfloat/generic/sub.c@ df4ed85

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since df4ed85 was df4ed85, checked in by Jakub Jermar <jakub@…>, 18 years ago

© versus ©

  • Property mode set to 100644
File size: 6.2 KB
RevLine 
[12c6f2d]1/*
[df4ed85]2 * Copyright (c) 2005 Josef Cejka
[12c6f2d]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
[846848a6]29 /** @addtogroup softfloat
30 * @{
31 */
32/** @file
33 */
34
[a96c570]35#include<sftypes.h>
36#include<sub.h>
37#include<comparison.h>
[12c6f2d]38
39/** Subtract two float32 numbers with same signs
40 */
41float32 subFloat32(float32 a, float32 b)
42{
43 int expdiff;
[aa59fa0]44 uint32_t exp1, exp2, frac1, frac2;
[12c6f2d]45 float32 result;
46
47 result.f = 0;
48
[a96c570]49 expdiff = a.parts.exp - b.parts.exp;
[1266543]50 if ((expdiff < 0 ) || ((expdiff == 0) && (a.parts.fraction < b.parts.fraction))) {
[12c6f2d]51 if (isFloat32NaN(b)) {
[1266543]52 /* TODO: fix SigNaN */
[12c6f2d]53 if (isFloat32SigNaN(b)) {
54 };
55 return b;
56 };
57
[a96c570]58 if (b.parts.exp == FLOAT32_MAX_EXPONENT) {
59 b.parts.sign = !b.parts.sign; /* num -(+-inf) = -+inf */
[12c6f2d]60 return b;
61 }
62
63 result.parts.sign = !a.parts.sign;
64
[1266543]65 frac1 = b.parts.fraction;
[a96c570]66 exp1 = b.parts.exp;
[1266543]67 frac2 = a.parts.fraction;
[a96c570]68 exp2 = a.parts.exp;
69 expdiff *= -1;
[12c6f2d]70 } else {
71 if (isFloat32NaN(a)) {
[1266543]72 /* TODO: fix SigNaN */
[a96c570]73 if (isFloat32SigNaN(a) || isFloat32SigNaN(b)) {
[12c6f2d]74 };
75 return a;
76 };
77
[a96c570]78 if (a.parts.exp == FLOAT32_MAX_EXPONENT) {
79 if (b.parts.exp == FLOAT32_MAX_EXPONENT) {
[12c6f2d]80 /* inf - inf => nan */
[1266543]81 /* TODO: fix exception */
[12c6f2d]82 result.binary = FLOAT32_NAN;
83 return result;
84 };
85 return a;
86 }
87
88 result.parts.sign = a.parts.sign;
89
[1266543]90 frac1 = a.parts.fraction;
[a96c570]91 exp1 = a.parts.exp;
[1266543]92 frac2 = b.parts.fraction;
[a96c570]93 exp2 = b.parts.exp;
[12c6f2d]94 };
95
[a96c570]96 if (exp1 == 0) {
[1266543]97 /* both are denormalized */
98 result.parts.fraction = frac1-frac2;
99 if (result.parts.fraction > frac1) {
100 /* TODO: underflow exception */
[12c6f2d]101 return result;
102 };
[a96c570]103 result.parts.exp = 0;
[12c6f2d]104 return result;
105 };
[a96c570]106
107 /* add hidden bit */
[1266543]108 frac1 |= FLOAT32_HIDDEN_BIT_MASK;
[a96c570]109
110 if (exp2 == 0) {
111 /* denormalized */
112 --expdiff;
113 } else {
114 /* normalized */
[1266543]115 frac2 |= FLOAT32_HIDDEN_BIT_MASK;
[a96c570]116 };
117
118 /* create some space for rounding */
[1266543]119 frac1 <<= 6;
120 frac2 <<= 6;
[a96c570]121
[1266543]122 if (expdiff > FLOAT32_FRACTION_SIZE + 1) {
[a96c570]123 goto done;
124 };
[12c6f2d]125
[1266543]126 frac1 = frac1 - (frac2 >> expdiff);
[a96c570]127done:
[1266543]128 /* TODO: find first nonzero digit and shift result and detect possibly underflow */
129 while ((exp1 > 0) && (!(frac1 & (FLOAT32_HIDDEN_BIT_MASK << 6 )))) {
[a96c570]130 --exp1;
[1266543]131 frac1 <<= 1;
132 /* TODO: fix underflow - frac1 == 0 does not necessary means underflow... */
[a96c570]133 };
[12c6f2d]134
[1266543]135 /* rounding - if first bit after fraction is set then round up */
136 frac1 += 0x20;
[a96c570]137
[1266543]138 if (frac1 & (FLOAT32_HIDDEN_BIT_MASK << 7)) {
[a96c570]139 ++exp1;
[1266543]140 frac1 >>= 1;
[a96c570]141 };
142
143 /*Clear hidden bit and shift */
[1266543]144 result.parts.fraction = ((frac1 >> 6) & (~FLOAT32_HIDDEN_BIT_MASK));
[a96c570]145 result.parts.exp = exp1;
146
147 return result;
148}
149
150/** Subtract two float64 numbers with same signs
151 */
152float64 subFloat64(float64 a, float64 b)
153{
154 int expdiff;
[aa59fa0]155 uint32_t exp1, exp2;
156 uint64_t frac1, frac2;
[a96c570]157 float64 result;
158
159 result.d = 0;
160
161 expdiff = a.parts.exp - b.parts.exp;
[1266543]162 if ((expdiff < 0 ) || ((expdiff == 0) && (a.parts.fraction < b.parts.fraction))) {
[a96c570]163 if (isFloat64NaN(b)) {
[1266543]164 /* TODO: fix SigNaN */
[a96c570]165 if (isFloat64SigNaN(b)) {
166 };
167 return b;
168 };
169
170 if (b.parts.exp == FLOAT64_MAX_EXPONENT) {
171 b.parts.sign = !b.parts.sign; /* num -(+-inf) = -+inf */
172 return b;
173 }
174
175 result.parts.sign = !a.parts.sign;
176
[1266543]177 frac1 = b.parts.fraction;
[a96c570]178 exp1 = b.parts.exp;
[1266543]179 frac2 = a.parts.fraction;
[a96c570]180 exp2 = a.parts.exp;
181 expdiff *= -1;
182 } else {
183 if (isFloat64NaN(a)) {
[1266543]184 /* TODO: fix SigNaN */
[a96c570]185 if (isFloat64SigNaN(a) || isFloat64SigNaN(b)) {
186 };
187 return a;
188 };
189
190 if (a.parts.exp == FLOAT64_MAX_EXPONENT) {
191 if (b.parts.exp == FLOAT64_MAX_EXPONENT) {
192 /* inf - inf => nan */
[1266543]193 /* TODO: fix exception */
[a96c570]194 result.binary = FLOAT64_NAN;
195 return result;
196 };
197 return a;
198 }
199
200 result.parts.sign = a.parts.sign;
201
[1266543]202 frac1 = a.parts.fraction;
[a96c570]203 exp1 = a.parts.exp;
[1266543]204 frac2 = b.parts.fraction;
[a96c570]205 exp2 = b.parts.exp;
206 };
[12c6f2d]207
[a96c570]208 if (exp1 == 0) {
[1266543]209 /* both are denormalized */
210 result.parts.fraction = frac1 - frac2;
211 if (result.parts.fraction > frac1) {
212 /* TODO: underflow exception */
[a96c570]213 return result;
214 };
215 result.parts.exp = 0;
216 return result;
217 };
218
219 /* add hidden bit */
[1266543]220 frac1 |= FLOAT64_HIDDEN_BIT_MASK;
[12c6f2d]221
[a96c570]222 if (exp2 == 0) {
223 /* denormalized */
[12c6f2d]224 --expdiff;
225 } else {
[a96c570]226 /* normalized */
[1266543]227 frac2 |= FLOAT64_HIDDEN_BIT_MASK;
[12c6f2d]228 };
229
[a96c570]230 /* create some space for rounding */
[1266543]231 frac1 <<= 6;
232 frac2 <<= 6;
[a96c570]233
[1266543]234 if (expdiff > FLOAT64_FRACTION_SIZE + 1) {
[12c6f2d]235 goto done;
236 };
237
[1266543]238 frac1 = frac1 - (frac2 >> expdiff);
[12c6f2d]239done:
[1266543]240 /* TODO: find first nonzero digit and shift result and detect possibly underflow */
241 while ((exp1 > 0) && (!(frac1 & (FLOAT64_HIDDEN_BIT_MASK << 6 )))) {
[a96c570]242 --exp1;
[1266543]243 frac1 <<= 1;
244 /* TODO: fix underflow - frac1 == 0 does not necessary means underflow... */
[12c6f2d]245 };
246
[1266543]247 /* rounding - if first bit after fraction is set then round up */
248 frac1 += 0x20;
[12c6f2d]249
[1266543]250 if (frac1 & (FLOAT64_HIDDEN_BIT_MASK << 7)) {
[12c6f2d]251 ++exp1;
[1266543]252 frac1 >>= 1;
[12c6f2d]253 };
254
[a96c570]255 /*Clear hidden bit and shift */
[1266543]256 result.parts.fraction = ((frac1 >> 6) & (~FLOAT64_HIDDEN_BIT_MASK));
[12c6f2d]257 result.parts.exp = exp1;
258
259 return result;
[a96c570]260}
[12c6f2d]261
[846848a6]262
263 /** @}
264 */
265
Note: See TracBrowser for help on using the repository browser.