source: mainline/uspace/lib/softfloat/sub.c@ c300bb5

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c300bb5 was 1433ecda, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix cstyle: make ccheck-fix and commit only files where all the changes are good.

  • Property mode set to 100644
File size: 12.2 KB
RevLine 
[12c6f2d]1/*
[df4ed85]2 * Copyright (c) 2005 Josef Cejka
[c67aff2]3 * Copyright (c) 2011 Petr Koupy
[12c6f2d]4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
[750636a]30/** @addtogroup softfloat
[846848a6]31 * @{
32 */
[c67aff2]33/** @file Substraction functions.
[846848a6]34 */
35
[2416085]36#include "sub.h"
37#include "comparison.h"
38#include "common.h"
[c0c38c7c]39#include "add.h"
[12c6f2d]40
[88d5c1e]41/** Subtract two single-precision floats with the same sign.
[c67aff2]42 *
43 * @param a First input operand.
44 * @param b Second input operand.
[88d5c1e]45 *
[c67aff2]46 * @return Result of substraction.
[88d5c1e]47 *
[12c6f2d]48 */
[88d5c1e]49float32 sub_float32(float32 a, float32 b)
[12c6f2d]50{
51 int expdiff;
[aa59fa0]52 uint32_t exp1, exp2, frac1, frac2;
[12c6f2d]53 float32 result;
[a35b458]54
[88d5c1e]55 result.bin = 0;
[a35b458]56
[a96c570]57 expdiff = a.parts.exp - b.parts.exp;
[1433ecda]58 if ((expdiff < 0) || ((expdiff == 0) &&
[88d5c1e]59 (a.parts.fraction < b.parts.fraction))) {
60 if (is_float32_nan(b)) {
61 if (is_float32_signan(b)) {
62 // TODO: fix SigNaN
[c67aff2]63 }
[a35b458]64
[12c6f2d]65 return b;
[c67aff2]66 }
[a35b458]67
[88d5c1e]68 if (b.parts.exp == FLOAT32_MAX_EXPONENT) {
69 /* num -(+-inf) = -+inf */
70 b.parts.sign = !b.parts.sign;
[12c6f2d]71 return b;
72 }
[a35b458]73
[88d5c1e]74 result.parts.sign = !a.parts.sign;
[a35b458]75
[1266543]76 frac1 = b.parts.fraction;
[a96c570]77 exp1 = b.parts.exp;
[1266543]78 frac2 = a.parts.fraction;
[a96c570]79 exp2 = a.parts.exp;
80 expdiff *= -1;
[12c6f2d]81 } else {
[88d5c1e]82 if (is_float32_nan(a)) {
83 if ((is_float32_signan(a)) || (is_float32_signan(b))) {
84 // TODO: fix SigNaN
[c67aff2]85 }
[a35b458]86
[12c6f2d]87 return a;
[c67aff2]88 }
[a35b458]89
[88d5c1e]90 if (a.parts.exp == FLOAT32_MAX_EXPONENT) {
[a96c570]91 if (b.parts.exp == FLOAT32_MAX_EXPONENT) {
[12c6f2d]92 /* inf - inf => nan */
[88d5c1e]93 // TODO: fix exception
94 result.bin = FLOAT32_NAN;
[12c6f2d]95 return result;
[c67aff2]96 }
[a35b458]97
[12c6f2d]98 return a;
99 }
[a35b458]100
[12c6f2d]101 result.parts.sign = a.parts.sign;
[a35b458]102
[1266543]103 frac1 = a.parts.fraction;
[a96c570]104 exp1 = a.parts.exp;
[1266543]105 frac2 = b.parts.fraction;
[88d5c1e]106 exp2 = b.parts.exp;
[c67aff2]107 }
[a35b458]108
[a96c570]109 if (exp1 == 0) {
[1266543]110 /* both are denormalized */
[c67aff2]111 result.parts.fraction = frac1 - frac2;
[1266543]112 if (result.parts.fraction > frac1) {
[88d5c1e]113 // TODO: underflow exception
[12c6f2d]114 return result;
[c67aff2]115 }
[a35b458]116
[a96c570]117 result.parts.exp = 0;
[12c6f2d]118 return result;
[c67aff2]119 }
[a35b458]120
[a96c570]121 /* add hidden bit */
[88d5c1e]122 frac1 |= FLOAT32_HIDDEN_BIT_MASK;
[a35b458]123
[a96c570]124 if (exp2 == 0) {
125 /* denormalized */
[88d5c1e]126 --expdiff;
[a96c570]127 } else {
128 /* normalized */
[1266543]129 frac2 |= FLOAT32_HIDDEN_BIT_MASK;
[c67aff2]130 }
[a35b458]131
[a96c570]132 /* create some space for rounding */
[1266543]133 frac1 <<= 6;
134 frac2 <<= 6;
[a35b458]135
[88d5c1e]136 if (expdiff > FLOAT32_FRACTION_SIZE + 1)
[c67aff2]137 goto done;
[a35b458]138
[1266543]139 frac1 = frac1 - (frac2 >> expdiff);
[a35b458]140
[a96c570]141done:
[1266543]142 /* TODO: find first nonzero digit and shift result and detect possibly underflow */
[1433ecda]143 while ((exp1 > 0) && (!(frac1 & (FLOAT32_HIDDEN_BIT_MASK << 6)))) {
[a96c570]144 --exp1;
[1266543]145 frac1 <<= 1;
[c67aff2]146 /* TODO: fix underflow - frac1 == 0 does not necessary means underflow... */
147 }
[a35b458]148
[1266543]149 /* rounding - if first bit after fraction is set then round up */
150 frac1 += 0x20;
[a35b458]151
[1266543]152 if (frac1 & (FLOAT32_HIDDEN_BIT_MASK << 7)) {
[a96c570]153 ++exp1;
[1266543]154 frac1 >>= 1;
[c67aff2]155 }
[a35b458]156
[c67aff2]157 /* Clear hidden bit and shift */
[88d5c1e]158 result.parts.fraction = ((frac1 >> 6) & (~FLOAT32_HIDDEN_BIT_MASK));
[a96c570]159 result.parts.exp = exp1;
[a35b458]160
[a96c570]161 return result;
162}
163
[88d5c1e]164/** Subtract two double-precision floats with the same sign.
[c67aff2]165 *
166 * @param a First input operand.
167 * @param b Second input operand.
[88d5c1e]168 *
[c67aff2]169 * @return Result of substraction.
[88d5c1e]170 *
[a96c570]171 */
[88d5c1e]172float64 sub_float64(float64 a, float64 b)
[a96c570]173{
174 int expdiff;
[aa59fa0]175 uint32_t exp1, exp2;
176 uint64_t frac1, frac2;
[a96c570]177 float64 result;
[a35b458]178
[88d5c1e]179 result.bin = 0;
[a35b458]180
[a96c570]181 expdiff = a.parts.exp - b.parts.exp;
[1433ecda]182 if ((expdiff < 0) ||
[88d5c1e]183 ((expdiff == 0) && (a.parts.fraction < b.parts.fraction))) {
184 if (is_float64_nan(b)) {
185 if (is_float64_signan(b)) {
186 // TODO: fix SigNaN
[c67aff2]187 }
[a35b458]188
[a96c570]189 return b;
[c67aff2]190 }
[a35b458]191
[88d5c1e]192 if (b.parts.exp == FLOAT64_MAX_EXPONENT) {
193 /* num -(+-inf) = -+inf */
194 b.parts.sign = !b.parts.sign;
[a96c570]195 return b;
196 }
[a35b458]197
[88d5c1e]198 result.parts.sign = !a.parts.sign;
[a35b458]199
[1266543]200 frac1 = b.parts.fraction;
[a96c570]201 exp1 = b.parts.exp;
[1266543]202 frac2 = a.parts.fraction;
[a96c570]203 exp2 = a.parts.exp;
204 expdiff *= -1;
205 } else {
[88d5c1e]206 if (is_float64_nan(a)) {
207 if (is_float64_signan(a) || is_float64_signan(b)) {
208 // TODO: fix SigNaN
[c67aff2]209 }
[a35b458]210
[a96c570]211 return a;
[c67aff2]212 }
[a35b458]213
[88d5c1e]214 if (a.parts.exp == FLOAT64_MAX_EXPONENT) {
[a96c570]215 if (b.parts.exp == FLOAT64_MAX_EXPONENT) {
216 /* inf - inf => nan */
[88d5c1e]217 // TODO: fix exception
218 result.bin = FLOAT64_NAN;
[a96c570]219 return result;
[c67aff2]220 }
[a35b458]221
[a96c570]222 return a;
223 }
[a35b458]224
[a96c570]225 result.parts.sign = a.parts.sign;
[a35b458]226
[1266543]227 frac1 = a.parts.fraction;
[a96c570]228 exp1 = a.parts.exp;
[1266543]229 frac2 = b.parts.fraction;
[88d5c1e]230 exp2 = b.parts.exp;
[c67aff2]231 }
[a35b458]232
[a96c570]233 if (exp1 == 0) {
[1266543]234 /* both are denormalized */
235 result.parts.fraction = frac1 - frac2;
236 if (result.parts.fraction > frac1) {
[88d5c1e]237 // TODO: underflow exception
[a96c570]238 return result;
[c67aff2]239 }
[a35b458]240
[a96c570]241 result.parts.exp = 0;
242 return result;
[c67aff2]243 }
[a35b458]244
[a96c570]245 /* add hidden bit */
[88d5c1e]246 frac1 |= FLOAT64_HIDDEN_BIT_MASK;
[a35b458]247
[a96c570]248 if (exp2 == 0) {
249 /* denormalized */
[88d5c1e]250 --expdiff;
[12c6f2d]251 } else {
[a96c570]252 /* normalized */
[1266543]253 frac2 |= FLOAT64_HIDDEN_BIT_MASK;
[c67aff2]254 }
[a35b458]255
[a96c570]256 /* create some space for rounding */
[1266543]257 frac1 <<= 6;
258 frac2 <<= 6;
[a35b458]259
[88d5c1e]260 if (expdiff > FLOAT64_FRACTION_SIZE + 1)
[c67aff2]261 goto done;
[a35b458]262
[1266543]263 frac1 = frac1 - (frac2 >> expdiff);
[a35b458]264
[12c6f2d]265done:
[1266543]266 /* TODO: find first nonzero digit and shift result and detect possibly underflow */
[1433ecda]267 while ((exp1 > 0) && (!(frac1 & (FLOAT64_HIDDEN_BIT_MASK << 6)))) {
[a96c570]268 --exp1;
[1266543]269 frac1 <<= 1;
[c67aff2]270 /* TODO: fix underflow - frac1 == 0 does not necessary means underflow... */
271 }
[a35b458]272
[1266543]273 /* rounding - if first bit after fraction is set then round up */
274 frac1 += 0x20;
[a35b458]275
[1266543]276 if (frac1 & (FLOAT64_HIDDEN_BIT_MASK << 7)) {
[12c6f2d]277 ++exp1;
[1266543]278 frac1 >>= 1;
[c67aff2]279 }
[a35b458]280
[c67aff2]281 /* Clear hidden bit and shift */
[88d5c1e]282 result.parts.fraction = ((frac1 >> 6) & (~FLOAT64_HIDDEN_BIT_MASK));
[12c6f2d]283 result.parts.exp = exp1;
[a35b458]284
[12c6f2d]285 return result;
[a96c570]286}
[12c6f2d]287
[88d5c1e]288/** Subtract two quadruple-precision floats with the same sign.
[c67aff2]289 *
290 * @param a First input operand.
291 * @param b Second input operand.
[88d5c1e]292 *
[c67aff2]293 * @return Result of substraction.
[88d5c1e]294 *
[c67aff2]295 */
[88d5c1e]296float128 sub_float128(float128 a, float128 b)
[c67aff2]297{
298 int expdiff;
299 uint32_t exp1, exp2;
300 uint64_t frac1_hi, frac1_lo, frac2_hi, frac2_lo, tmp_hi, tmp_lo;
301 float128 result;
[a35b458]302
[88d5c1e]303 result.bin.hi = 0;
304 result.bin.lo = 0;
[a35b458]305
[c67aff2]306 expdiff = a.parts.exp - b.parts.exp;
[1433ecda]307 if ((expdiff < 0) || ((expdiff == 0) &&
[c67aff2]308 lt128(a.parts.frac_hi, a.parts.frac_lo, b.parts.frac_hi, b.parts.frac_lo))) {
[88d5c1e]309 if (is_float128_nan(b)) {
310 if (is_float128_signan(b)) {
311 // TODO: fix SigNaN
[c67aff2]312 }
[a35b458]313
[c67aff2]314 return b;
315 }
[a35b458]316
[c67aff2]317 if (b.parts.exp == FLOAT128_MAX_EXPONENT) {
[88d5c1e]318 /* num -(+-inf) = -+inf */
319 b.parts.sign = !b.parts.sign;
[c67aff2]320 return b;
321 }
[a35b458]322
[c67aff2]323 result.parts.sign = !a.parts.sign;
[a35b458]324
[c67aff2]325 frac1_hi = b.parts.frac_hi;
326 frac1_lo = b.parts.frac_lo;
327 exp1 = b.parts.exp;
328 frac2_hi = a.parts.frac_hi;
329 frac2_lo = a.parts.frac_lo;
330 exp2 = a.parts.exp;
331 expdiff *= -1;
332 } else {
[88d5c1e]333 if (is_float128_nan(a)) {
334 if (is_float128_signan(a) || is_float128_signan(b)) {
335 // TODO: fix SigNaN
[c67aff2]336 }
[a35b458]337
[c67aff2]338 return a;
339 }
[a35b458]340
[c67aff2]341 if (a.parts.exp == FLOAT128_MAX_EXPONENT) {
342 if (b.parts.exp == FLOAT128_MAX_EXPONENT) {
343 /* inf - inf => nan */
[88d5c1e]344 // TODO: fix exception
345 result.bin.hi = FLOAT128_NAN_HI;
346 result.bin.lo = FLOAT128_NAN_LO;
[c67aff2]347 return result;
348 }
349 return a;
350 }
[a35b458]351
[c67aff2]352 result.parts.sign = a.parts.sign;
[a35b458]353
[c67aff2]354 frac1_hi = a.parts.frac_hi;
355 frac1_lo = a.parts.frac_lo;
356 exp1 = a.parts.exp;
357 frac2_hi = b.parts.frac_hi;
358 frac2_lo = b.parts.frac_lo;
359 exp2 = b.parts.exp;
360 }
[a35b458]361
[c67aff2]362 if (exp1 == 0) {
363 /* both are denormalized */
364 sub128(frac1_hi, frac1_lo, frac2_hi, frac2_lo, &tmp_hi, &tmp_lo);
365 result.parts.frac_hi = tmp_hi;
366 result.parts.frac_lo = tmp_lo;
367 if (lt128(frac1_hi, frac1_lo, result.parts.frac_hi, result.parts.frac_lo)) {
[88d5c1e]368 // TODO: underflow exception
[c67aff2]369 return result;
370 }
[a35b458]371
[c67aff2]372 result.parts.exp = 0;
373 return result;
374 }
[a35b458]375
[c67aff2]376 /* add hidden bit */
377 or128(frac1_hi, frac1_lo,
378 FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
379 &frac1_hi, &frac1_lo);
[a35b458]380
[c67aff2]381 if (exp2 == 0) {
382 /* denormalized */
383 --expdiff;
384 } else {
385 /* normalized */
386 or128(frac2_hi, frac2_lo,
387 FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
388 &frac2_hi, &frac2_lo);
389 }
[a35b458]390
[c67aff2]391 /* create some space for rounding */
392 lshift128(frac1_hi, frac1_lo, 6, &frac1_hi, &frac1_lo);
393 lshift128(frac2_hi, frac2_lo, 6, &frac2_hi, &frac2_lo);
[a35b458]394
[88d5c1e]395 if (expdiff > FLOAT128_FRACTION_SIZE + 1)
[c67aff2]396 goto done;
[a35b458]397
[c67aff2]398 rshift128(frac2_hi, frac2_lo, expdiff, &tmp_hi, &tmp_lo);
399 sub128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &frac1_hi, &frac1_lo);
[a35b458]400
[c67aff2]401done:
402 /* TODO: find first nonzero digit and shift result and detect possibly underflow */
403 lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO, 6,
404 &tmp_hi, &tmp_lo);
405 and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
406 while ((exp1 > 0) && (!lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo))) {
407 --exp1;
408 lshift128(frac1_hi, frac1_lo, 1, &frac1_hi, &frac1_lo);
409 /* TODO: fix underflow - frac1 == 0 does not necessary means underflow... */
[a35b458]410
[c67aff2]411 lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO, 6,
412 &tmp_hi, &tmp_lo);
413 and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
414 }
[a35b458]415
[c67aff2]416 /* rounding - if first bit after fraction is set then round up */
417 add128(frac1_hi, frac1_lo, 0x0ll, 0x20ll, &frac1_hi, &frac1_lo);
[a35b458]418
[c67aff2]419 lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO, 7,
[1433ecda]420 &tmp_hi, &tmp_lo);
[c67aff2]421 and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
422 if (lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
423 ++exp1;
424 rshift128(frac1_hi, frac1_lo, 1, &frac1_hi, &frac1_lo);
425 }
[a35b458]426
[c67aff2]427 /* Clear hidden bit and shift */
428 rshift128(frac1_hi, frac1_lo, 6, &frac1_hi, &frac1_lo);
429 not128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
430 &tmp_hi, &tmp_lo);
431 and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
432 result.parts.frac_hi = tmp_hi;
433 result.parts.frac_lo = tmp_lo;
[a35b458]434
[c67aff2]435 result.parts.exp = exp1;
[a35b458]436
[c67aff2]437 return result;
438}
439
[c0c38c7c]440#ifdef float32_t
441
442float32_t __subsf3(float32_t a, float32_t b)
443{
444 float32_u ua;
445 ua.val = a;
[a35b458]446
[c0c38c7c]447 float32_u ub;
448 ub.val = b;
[a35b458]449
[c0c38c7c]450 float32_u res;
[a35b458]451
[c0c38c7c]452 if (ua.data.parts.sign != ub.data.parts.sign) {
453 ub.data.parts.sign = !ub.data.parts.sign;
454 res.data = add_float32(ua.data, ub.data);
455 } else
456 res.data = sub_float32(ua.data, ub.data);
[a35b458]457
[c0c38c7c]458 return res.val;
459}
460
461float32_t __aeabi_fsub(float32_t a, float32_t b)
462{
463 float32_u ua;
464 ua.val = a;
[a35b458]465
[c0c38c7c]466 float32_u ub;
467 ub.val = b;
[a35b458]468
[c0c38c7c]469 float32_u res;
[a35b458]470
[c0c38c7c]471 if (ua.data.parts.sign != ub.data.parts.sign) {
472 ub.data.parts.sign = !ub.data.parts.sign;
473 res.data = add_float32(ua.data, ub.data);
474 } else
475 res.data = sub_float32(ua.data, ub.data);
[a35b458]476
[c0c38c7c]477 return res.val;
478}
479
480#endif
481
482#ifdef float64_t
483
484float64_t __subdf3(float64_t a, float64_t b)
485{
486 float64_u ua;
487 ua.val = a;
[a35b458]488
[c0c38c7c]489 float64_u ub;
490 ub.val = b;
[a35b458]491
[c0c38c7c]492 float64_u res;
[a35b458]493
[c0c38c7c]494 if (ua.data.parts.sign != ub.data.parts.sign) {
495 ub.data.parts.sign = !ub.data.parts.sign;
496 res.data = add_float64(ua.data, ub.data);
497 } else
498 res.data = sub_float64(ua.data, ub.data);
[a35b458]499
[c0c38c7c]500 return res.val;
501}
502
503float64_t __aeabi_dsub(float64_t a, float64_t b)
504{
505 float64_u ua;
506 ua.val = a;
[a35b458]507
[c0c38c7c]508 float64_u ub;
509 ub.val = b;
[a35b458]510
[c0c38c7c]511 float64_u res;
[a35b458]512
[c0c38c7c]513 if (ua.data.parts.sign != ub.data.parts.sign) {
514 ub.data.parts.sign = !ub.data.parts.sign;
515 res.data = add_float64(ua.data, ub.data);
516 } else
517 res.data = sub_float64(ua.data, ub.data);
[a35b458]518
[c0c38c7c]519 return res.val;
520}
521
522#endif
523
524#ifdef float128_t
525
526float128_t __subtf3(float128_t a, float128_t b)
527{
528 float128_u ua;
529 ua.val = a;
[a35b458]530
[c0c38c7c]531 float128_u ub;
532 ub.val = b;
[a35b458]533
[c0c38c7c]534 float128_u res;
[a35b458]535
[c0c38c7c]536 if (ua.data.parts.sign != ub.data.parts.sign) {
537 ub.data.parts.sign = !ub.data.parts.sign;
538 res.data = add_float128(ua.data, ub.data);
539 } else
540 res.data = sub_float128(ua.data, ub.data);
[a35b458]541
[c0c38c7c]542 return res.val;
543}
544
545void _Qp_sub(float128_t *c, float128_t *a, float128_t *b)
546{
547 *c = __subtf3(*a, *b);
548}
549
550#endif
551
[750636a]552/** @}
[846848a6]553 */
Note: See TracBrowser for help on using the repository browser.