source: mainline/uspace/lib/c/generic/ieee_double.c@ 38db6288

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

Add a missing copyright message and cstyle.

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