source: mainline/uspace/lib/c/generic/ieee_double.c@ 34b9299

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

printf() full floating point support.
(Thanks to Adam Hraska.)

  • Property mode set to 100644
File size: 3.8 KB
RevLine 
[34b9299]1/*
2 * Copyright (c) 2012 Adam Hraska
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#include <ieee_double.h>
29
30#include <assert.h>
31
32/** Returns an easily processible description of the double val.
33 */
34ieee_double_t extract_ieee_double(double val)
35{
36 const uint64_t significand_mask = 0xfffffffffffffULL;
37 const uint64_t exponent_mask = 0x7ff0000000000000ULL;
38 const int exponent_shift = 64 - 11 - 1;
39 const uint64_t sign_mask = 0x8000000000000000ULL;
40
41 const int special_exponent = 0x7ff;
42 const int denormal_exponent = 0;
43 const uint64_t hidden_bit = (1ULL << 52);
44 const int exponent_bias = 1075;
45
46 assert(sizeof(val) == sizeof(uint64_t));
47
48 union {
49 uint64_t num;
50 double val;
51 } bits;
52
53 bits.val = val;
54
55 /*
56 * Extract the binary ieee representation of the double.
57 * Relies on integers having the same endianness as doubles.
58 */
59 uint64_t num = bits.num;
60
61 ieee_double_t ret;
62
63 /* Determine the sign. */
64 ret.is_negative = ((num & sign_mask) != 0);
65
66 /* Extract the exponent. */
67 int raw_exponent = (num & exponent_mask) >> exponent_shift;
68
69 /* The extracted raw significand may not contain the hidden bit */
70 uint64_t raw_significand = num & significand_mask;
71
72 ret.is_special = (raw_exponent == special_exponent);
73
74 /* NaN or infinity */
75 if (ret.is_special) {
76 ret.is_infinity = (raw_significand == 0);
77 ret.is_nan = (raw_significand != 0);
78
79 /* These are not valid for special numbers but init them anyway. */
80 ret.is_denormal = true;
81 ret.is_accuracy_step = false;
82 ret.pos_val.significand = 0;
83 ret.pos_val.exponent = 0;
84 } else {
85 ret.is_infinity = false;
86 ret.is_nan = false;
87
88 ret.is_denormal = (raw_exponent == denormal_exponent);
89
90 /* Denormal or zero. */
91 if (ret.is_denormal) {
92 ret.pos_val.significand = raw_significand;
93 ret.pos_val.exponent = 1 - exponent_bias;
94 ret.is_accuracy_step = false;
95 } else {
96 ret.pos_val.significand = raw_significand + hidden_bit;
97 ret.pos_val.exponent = raw_exponent - exponent_bias;
98
99 /* The predecessor is closer to val than the successor
100 * if val is a normal value of the form 2^k (hence
101 * raw_significand == 0) with the only exception being
102 * the smallest normal (raw_exponent == 1). The smallest
103 * normal's predecessor is the largest denormal and denormals
104 * do not get an extra bit of precision because their exponent
105 * stays the same (ie it does not decrease from k to k-1).
106 */
107 ret.is_accuracy_step = (raw_significand == 0) && (raw_exponent != 1);
108 }
109 }
110
111 return ret;
112}
113
Note: See TracBrowser for help on using the repository browser.