source: mainline/uspace/lib/softfloat/div.c@ 88e2c82

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

Fix block comment formatting (ccheck).

  • Property mode set to 100644
File size: 13.5 KB
Line 
1/*
2 * Copyright (c) 2005 Josef Cejka
3 * Copyright (c) 2011 Petr Koupy
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
30/** @addtogroup softfloat
31 * @{
32 */
33/** @file Division functions.
34 */
35
36#include "add.h"
37#include "div.h"
38#include "comparison.h"
39#include "mul.h"
40#include "common.h"
41
42/** Divide two single-precision floats.
43 *
44 * @param a Nominator.
45 * @param b Denominator.
46 *
47 * @return Result of division.
48 *
49 */
50float32 div_float32(float32 a, float32 b)
51{
52 float32 result;
53 int32_t aexp, bexp, cexp;
54 uint64_t afrac, bfrac, cfrac;
55
56 result.parts.sign = a.parts.sign ^ b.parts.sign;
57
58 if (is_float32_nan(a)) {
59 if (is_float32_signan(a)) {
60 // FIXME: SigNaN
61 }
62 /* NaN */
63 return a;
64 }
65
66 if (is_float32_nan(b)) {
67 if (is_float32_signan(b)) {
68 // FIXME: SigNaN
69 }
70 /* NaN */
71 return b;
72 }
73
74 if (is_float32_infinity(a)) {
75 if (is_float32_infinity(b)) {
76 /*FIXME: inf / inf */
77 result.bin = FLOAT32_NAN;
78 return result;
79 }
80 /* inf / num */
81 result.parts.exp = a.parts.exp;
82 result.parts.fraction = a.parts.fraction;
83 return result;
84 }
85
86 if (is_float32_infinity(b)) {
87 if (is_float32_zero(a)) {
88 /* FIXME 0 / inf */
89 result.parts.exp = 0;
90 result.parts.fraction = 0;
91 return result;
92 }
93 /* FIXME: num / inf*/
94 result.parts.exp = 0;
95 result.parts.fraction = 0;
96 return result;
97 }
98
99 if (is_float32_zero(b)) {
100 if (is_float32_zero(a)) {
101 /*FIXME: 0 / 0*/
102 result.bin = FLOAT32_NAN;
103 return result;
104 }
105 /* FIXME: division by zero */
106 result.parts.exp = 0;
107 result.parts.fraction = 0;
108 return result;
109 }
110
111 afrac = a.parts.fraction;
112 aexp = a.parts.exp;
113 bfrac = b.parts.fraction;
114 bexp = b.parts.exp;
115
116 /* denormalized numbers */
117 if (aexp == 0) {
118 if (afrac == 0) {
119 result.parts.exp = 0;
120 result.parts.fraction = 0;
121 return result;
122 }
123
124 /* normalize it*/
125 afrac <<= 1;
126 /* afrac is nonzero => it must stop */
127 while (!(afrac & FLOAT32_HIDDEN_BIT_MASK)) {
128 afrac <<= 1;
129 aexp--;
130 }
131 }
132
133 if (bexp == 0) {
134 bfrac <<= 1;
135 /* bfrac is nonzero => it must stop */
136 while (!(bfrac & FLOAT32_HIDDEN_BIT_MASK)) {
137 bfrac <<= 1;
138 bexp--;
139 }
140 }
141
142 afrac = (afrac | FLOAT32_HIDDEN_BIT_MASK) << (32 - FLOAT32_FRACTION_SIZE - 1);
143 bfrac = (bfrac | FLOAT32_HIDDEN_BIT_MASK) << (32 - FLOAT32_FRACTION_SIZE);
144
145 if (bfrac <= (afrac << 1)) {
146 afrac >>= 1;
147 aexp++;
148 }
149
150 cexp = aexp - bexp + FLOAT32_BIAS - 2;
151
152 cfrac = (afrac << 32) / bfrac;
153 if ((cfrac & 0x3F) == 0) {
154 cfrac |= (bfrac * cfrac != afrac << 32);
155 }
156
157 /* pack and round */
158
159 /* find first nonzero digit and shift result and detect possibly underflow */
160 while ((cexp > 0) && (cfrac) && (!(cfrac & (FLOAT32_HIDDEN_BIT_MASK << 7)))) {
161 cexp--;
162 cfrac <<= 1;
163 /* TODO: fix underflow */
164 }
165
166 cfrac += (0x1 << 6); /* FIXME: 7 is not sure*/
167
168 if (cfrac & (FLOAT32_HIDDEN_BIT_MASK << 7)) {
169 ++cexp;
170 cfrac >>= 1;
171 }
172
173 /* check overflow */
174 if (cexp >= FLOAT32_MAX_EXPONENT) {
175 /* FIXME: overflow, return infinity */
176 result.parts.exp = FLOAT32_MAX_EXPONENT;
177 result.parts.fraction = 0;
178 return result;
179 }
180
181 if (cexp < 0) {
182 /* FIXME: underflow */
183 result.parts.exp = 0;
184 if ((cexp + FLOAT32_FRACTION_SIZE) < 0) {
185 result.parts.fraction = 0;
186 return result;
187 }
188 cfrac >>= 1;
189 while (cexp < 0) {
190 cexp++;
191 cfrac >>= 1;
192 }
193 } else {
194 result.parts.exp = (uint32_t) cexp;
195 }
196
197 result.parts.fraction = ((cfrac >> 6) & (~FLOAT32_HIDDEN_BIT_MASK));
198
199 return result;
200}
201
202/** Divide two double-precision floats.
203 *
204 * @param a Nominator.
205 * @param b Denominator.
206 *
207 * @return Result of division.
208 *
209 */
210float64 div_float64(float64 a, float64 b)
211{
212 float64 result;
213 int64_t aexp, bexp, cexp;
214 uint64_t afrac, bfrac, cfrac;
215 uint64_t remlo, remhi;
216 uint64_t tmplo, tmphi;
217
218 result.parts.sign = a.parts.sign ^ b.parts.sign;
219
220 if (is_float64_nan(a)) {
221 if (is_float64_signan(b)) {
222 // FIXME: SigNaN
223 return b;
224 }
225
226 if (is_float64_signan(a)) {
227 // FIXME: SigNaN
228 }
229 /* NaN */
230 return a;
231 }
232
233 if (is_float64_nan(b)) {
234 if (is_float64_signan(b)) {
235 // FIXME: SigNaN
236 }
237 /* NaN */
238 return b;
239 }
240
241 if (is_float64_infinity(a)) {
242 if (is_float64_infinity(b) || is_float64_zero(b)) {
243 // FIXME: inf / inf
244 result.bin = FLOAT64_NAN;
245 return result;
246 }
247 /* inf / num */
248 result.parts.exp = a.parts.exp;
249 result.parts.fraction = a.parts.fraction;
250 return result;
251 }
252
253 if (is_float64_infinity(b)) {
254 if (is_float64_zero(a)) {
255 /* FIXME 0 / inf */
256 result.parts.exp = 0;
257 result.parts.fraction = 0;
258 return result;
259 }
260 /* FIXME: num / inf*/
261 result.parts.exp = 0;
262 result.parts.fraction = 0;
263 return result;
264 }
265
266 if (is_float64_zero(b)) {
267 if (is_float64_zero(a)) {
268 /*FIXME: 0 / 0*/
269 result.bin = FLOAT64_NAN;
270 return result;
271 }
272 /* FIXME: division by zero */
273 result.parts.exp = 0;
274 result.parts.fraction = 0;
275 return result;
276 }
277
278 afrac = a.parts.fraction;
279 aexp = a.parts.exp;
280 bfrac = b.parts.fraction;
281 bexp = b.parts.exp;
282
283 /* denormalized numbers */
284 if (aexp == 0) {
285 if (afrac == 0) {
286 result.parts.exp = 0;
287 result.parts.fraction = 0;
288 return result;
289 }
290
291 /* normalize it*/
292 aexp++;
293 /* afrac is nonzero => it must stop */
294 while (!(afrac & FLOAT64_HIDDEN_BIT_MASK)) {
295 afrac <<= 1;
296 aexp--;
297 }
298 }
299
300 if (bexp == 0) {
301 bexp++;
302 /* bfrac is nonzero => it must stop */
303 while (!(bfrac & FLOAT64_HIDDEN_BIT_MASK)) {
304 bfrac <<= 1;
305 bexp--;
306 }
307 }
308
309 afrac = (afrac | FLOAT64_HIDDEN_BIT_MASK) << (64 - FLOAT64_FRACTION_SIZE - 2);
310 bfrac = (bfrac | FLOAT64_HIDDEN_BIT_MASK) << (64 - FLOAT64_FRACTION_SIZE - 1);
311
312 if (bfrac <= (afrac << 1)) {
313 afrac >>= 1;
314 aexp++;
315 }
316
317 cexp = aexp - bexp + FLOAT64_BIAS - 2;
318
319 cfrac = div128est(afrac, 0x0ll, bfrac);
320
321 if ((cfrac & 0x1FF) <= 2) {
322 mul64(bfrac, cfrac, &tmphi, &tmplo);
323 sub128(afrac, 0x0ll, tmphi, tmplo, &remhi, &remlo);
324
325 while ((int64_t) remhi < 0) {
326 cfrac--;
327 add128(remhi, remlo, 0x0ll, bfrac, &remhi, &remlo);
328 }
329 cfrac |= (remlo != 0);
330 }
331
332 /* round and shift */
333 result = finish_float64(cexp, cfrac, result.parts.sign);
334 return result;
335}
336
337/** Divide two quadruple-precision floats.
338 *
339 * @param a Nominator.
340 * @param b Denominator.
341 *
342 * @return Result of division.
343 *
344 */
345float128 div_float128(float128 a, float128 b)
346{
347 float128 result;
348 int64_t aexp, bexp, cexp;
349 uint64_t afrac_hi, afrac_lo, bfrac_hi, bfrac_lo, cfrac_hi, cfrac_lo;
350 uint64_t shift_out;
351 uint64_t rem_hihi, rem_hilo, rem_lohi, rem_lolo;
352 uint64_t tmp_hihi, tmp_hilo, tmp_lohi, tmp_lolo;
353
354 result.parts.sign = a.parts.sign ^ b.parts.sign;
355
356 if (is_float128_nan(a)) {
357 if (is_float128_signan(b)) {
358 // FIXME: SigNaN
359 return b;
360 }
361
362 if (is_float128_signan(a)) {
363 // FIXME: SigNaN
364 }
365 /* NaN */
366 return a;
367 }
368
369 if (is_float128_nan(b)) {
370 if (is_float128_signan(b)) {
371 // FIXME: SigNaN
372 }
373 /* NaN */
374 return b;
375 }
376
377 if (is_float128_infinity(a)) {
378 if (is_float128_infinity(b) || is_float128_zero(b)) {
379 // FIXME: inf / inf
380 result.bin.hi = FLOAT128_NAN_HI;
381 result.bin.lo = FLOAT128_NAN_LO;
382 return result;
383 }
384 /* inf / num */
385 result.parts.exp = a.parts.exp;
386 result.parts.frac_hi = a.parts.frac_hi;
387 result.parts.frac_lo = a.parts.frac_lo;
388 return result;
389 }
390
391 if (is_float128_infinity(b)) {
392 if (is_float128_zero(a)) {
393 // FIXME 0 / inf
394 result.parts.exp = 0;
395 result.parts.frac_hi = 0;
396 result.parts.frac_lo = 0;
397 return result;
398 }
399 // FIXME: num / inf
400 result.parts.exp = 0;
401 result.parts.frac_hi = 0;
402 result.parts.frac_lo = 0;
403 return result;
404 }
405
406 if (is_float128_zero(b)) {
407 if (is_float128_zero(a)) {
408 // FIXME: 0 / 0
409 result.bin.hi = FLOAT128_NAN_HI;
410 result.bin.lo = FLOAT128_NAN_LO;
411 return result;
412 }
413 // FIXME: division by zero
414 result.parts.exp = 0;
415 result.parts.frac_hi = 0;
416 result.parts.frac_lo = 0;
417 return result;
418 }
419
420 afrac_hi = a.parts.frac_hi;
421 afrac_lo = a.parts.frac_lo;
422 aexp = a.parts.exp;
423 bfrac_hi = b.parts.frac_hi;
424 bfrac_lo = b.parts.frac_lo;
425 bexp = b.parts.exp;
426
427 /* denormalized numbers */
428 if (aexp == 0) {
429 if (eq128(afrac_hi, afrac_lo, 0x0ll, 0x0ll)) {
430 result.parts.exp = 0;
431 result.parts.frac_hi = 0;
432 result.parts.frac_lo = 0;
433 return result;
434 }
435
436 /* normalize it*/
437 aexp++;
438 /* afrac is nonzero => it must stop */
439 and128(afrac_hi, afrac_lo,
440 FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
441 &tmp_hihi, &tmp_lolo);
442 while (!lt128(0x0ll, 0x0ll, tmp_hihi, tmp_lolo)) {
443 lshift128(afrac_hi, afrac_lo, 1, &afrac_hi, &afrac_lo);
444 aexp--;
445 }
446 }
447
448 if (bexp == 0) {
449 bexp++;
450 /* bfrac is nonzero => it must stop */
451 and128(bfrac_hi, bfrac_lo,
452 FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
453 &tmp_hihi, &tmp_lolo);
454 while (!lt128(0x0ll, 0x0ll, tmp_hihi, tmp_lolo)) {
455 lshift128(bfrac_hi, bfrac_lo, 1, &bfrac_hi, &bfrac_lo);
456 bexp--;
457 }
458 }
459
460 or128(afrac_hi, afrac_lo,
461 FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
462 &afrac_hi, &afrac_lo);
463 lshift128(afrac_hi, afrac_lo,
464 (128 - FLOAT128_FRACTION_SIZE - 1), &afrac_hi, &afrac_lo);
465 or128(bfrac_hi, bfrac_lo,
466 FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
467 &bfrac_hi, &bfrac_lo);
468 lshift128(bfrac_hi, bfrac_lo,
469 (128 - FLOAT128_FRACTION_SIZE - 1), &bfrac_hi, &bfrac_lo);
470
471 if (le128(bfrac_hi, bfrac_lo, afrac_hi, afrac_lo)) {
472 rshift128(afrac_hi, afrac_lo, 1, &afrac_hi, &afrac_lo);
473 aexp++;
474 }
475
476 cexp = aexp - bexp + FLOAT128_BIAS - 2;
477
478 cfrac_hi = div128est(afrac_hi, afrac_lo, bfrac_hi);
479
480 mul128(bfrac_hi, bfrac_lo, 0x0ll, cfrac_hi,
481 &tmp_lolo /* dummy */, &tmp_hihi, &tmp_hilo, &tmp_lohi);
482
483 /*
484 * sub192(afrac_hi, afrac_lo, 0,
485 * tmp_hihi, tmp_hilo, tmp_lohi
486 * &rem_hihi, &rem_hilo, &rem_lohi);
487 */
488 sub128(afrac_hi, afrac_lo, tmp_hihi, tmp_hilo, &rem_hihi, &rem_hilo);
489 if (tmp_lohi > 0) {
490 sub128(rem_hihi, rem_hilo, 0x0ll, 0x1ll, &rem_hihi, &rem_hilo);
491 }
492 rem_lohi = -tmp_lohi;
493
494 while ((int64_t) rem_hihi < 0) {
495 --cfrac_hi;
496 /*
497 * add192(rem_hihi, rem_hilo, rem_lohi,
498 * 0, bfrac_hi, bfrac_lo,
499 * &rem_hihi, &rem_hilo, &rem_lohi);
500 */
501 add128(rem_hilo, rem_lohi, bfrac_hi, bfrac_lo, &rem_hilo, &rem_lohi);
502 if (lt128(rem_hilo, rem_lohi, bfrac_hi, bfrac_lo)) {
503 ++rem_hihi;
504 }
505 }
506
507 cfrac_lo = div128est(rem_hilo, rem_lohi, bfrac_lo);
508
509 if ((cfrac_lo & 0x3FFF) <= 4) {
510 mul128(bfrac_hi, bfrac_lo, 0x0ll, cfrac_lo,
511 &tmp_hihi /* dummy */, &tmp_hilo, &tmp_lohi, &tmp_lolo);
512
513 /*
514 * sub192(rem_hilo, rem_lohi, 0,
515 * tmp_hilo, tmp_lohi, tmp_lolo,
516 * &rem_hilo, &rem_lohi, &rem_lolo);
517 */
518 sub128(rem_hilo, rem_lohi, tmp_hilo, tmp_lohi, &rem_hilo, &rem_lohi);
519 if (tmp_lolo > 0) {
520 sub128(rem_hilo, rem_lohi, 0x0ll, 0x1ll, &rem_hilo, &rem_lohi);
521 }
522 rem_lolo = -tmp_lolo;
523
524 while ((int64_t) rem_hilo < 0) {
525 --cfrac_lo;
526 /*
527 * add192(rem_hilo, rem_lohi, rem_lolo,
528 * 0, bfrac_hi, bfrac_lo,
529 * &rem_hilo, &rem_lohi, &rem_lolo);
530 */
531 add128(rem_lohi, rem_lolo, bfrac_hi, bfrac_lo, &rem_lohi, &rem_lolo);
532 if (lt128(rem_lohi, rem_lolo, bfrac_hi, bfrac_lo)) {
533 ++rem_hilo;
534 }
535 }
536
537 cfrac_lo |= ((rem_hilo | rem_lohi | rem_lolo) != 0);
538 }
539
540 shift_out = cfrac_lo << (64 - (128 - FLOAT128_FRACTION_SIZE - 1));
541 rshift128(cfrac_hi, cfrac_lo, (128 - FLOAT128_FRACTION_SIZE - 1),
542 &cfrac_hi, &cfrac_lo);
543
544 result = finish_float128(cexp, cfrac_hi, cfrac_lo, result.parts.sign, shift_out);
545 return result;
546}
547
548#ifdef float32_t
549
550float32_t __divsf3(float32_t a, float32_t b)
551{
552 float32_u ua;
553 ua.val = a;
554
555 float32_u ub;
556 ub.val = b;
557
558 float32_u res;
559 res.data = div_float32(ua.data, ub.data);
560
561 return res.val;
562}
563
564float32_t __aeabi_fdiv(float32_t a, float32_t b)
565{
566 float32_u ua;
567 ua.val = a;
568
569 float32_u ub;
570 ub.val = b;
571
572 float32_u res;
573 res.data = div_float32(ua.data, ub.data);
574
575 return res.val;
576}
577
578#endif
579
580#ifdef float64_t
581
582float64_t __divdf3(float64_t a, float64_t b)
583{
584 float64_u ua;
585 ua.val = a;
586
587 float64_u ub;
588 ub.val = b;
589
590 float64_u res;
591 res.data = div_float64(ua.data, ub.data);
592
593 return res.val;
594}
595
596float64_t __aeabi_ddiv(float64_t a, float64_t b)
597{
598 float64_u ua;
599 ua.val = a;
600
601 float64_u ub;
602 ub.val = b;
603
604 float64_u res;
605 res.data = div_float64(ua.data, ub.data);
606
607 return res.val;
608}
609
610#endif
611
612#ifdef float128_t
613
614float128_t __divtf3(float128_t a, float128_t b)
615{
616 float128_u ua;
617 ua.val = a;
618
619 float128_u ub;
620 ub.val = b;
621
622 float128_u res;
623 res.data = div_float128(ua.data, ub.data);
624
625 return res.val;
626}
627
628void _Qp_div(float128_t *c, float128_t *a, float128_t *b)
629{
630 *c = __divtf3(*a, *b);
631}
632
633#endif
634
635/** @}
636 */
Note: See TracBrowser for help on using the repository browser.