1 /*
2 * rpf.c: Conversion of float to reduced precision format values
3 *
4 * Written by: Stefan Frank
5 * Richard Krampfl
6 * Ullrich Hafner
7 *
8 * This file is part of FIASCO (�F�ractal �I�mage �A�nd �S�equence �CO�dec)
9 * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de>
10 */
11
12 /*
13 * $Date: 2000/06/14 20:49:37 $
14 * $Author: hafner $
15 * $Revision: 5.1 $
16 * $State: Exp $
17 */
18
19 #include "pm_config.h"
20 #include "config.h"
21 #include "mallocvar.h"
22
23 #include "types.h"
24 #include "macros.h"
25 #include "error.h"
26
27 #include "misc.h"
28 #include "rpf.h"
29
30 int const RPF_ZERO = -1;
31
32 /*****************************************************************************
33
34 private code
35
36 *****************************************************************************/
37
38
39 typedef struct {
40 double fraction;
41 int exponent;
42 } FracExp;
43
44
45
46 static FracExp
fracExpFromDouble(double const x)47 fracExpFromDouble(double const x) {
48
49 FracExp retval;
50
51 retval.fraction = frexp(x, &retval.exponent);
52
53 return retval;
54 }
55
56
57
58 int
rtob(real_t const f,const rpf_t * const rpfP)59 rtob (real_t const f,
60 const rpf_t * const rpfP)
61 /*
62 * Convert real number 'f' into fixed point format.
63 * The real number in [-'range'; +'range'] is scaled to [-1 ; +1].
64 * Sign and the first 'precision' - 1 bits of the mantissa are
65 * packed into one integer.
66 *
67 * Return value:
68 * real value in reduced precision format
69 */
70 {
71 /*
72 * Extract mantissa (23 Bits), exponent (8 Bits) and sign (1 Bit)
73 */
74
75 double const normalized = f / rpfP->range;
76 /* 'f' scaled to [-1,+1] */
77 FracExp const fracExp = fracExpFromDouble(normalized);
78 unsigned int const signedMantissa =
79 (unsigned int) (fracExp.fraction * (1<<23));
80
81 unsigned int mantissa;
82 unsigned int sign; /* 0 for positive; 1 for negative */
83
84 if (signedMantissa < 0) {
85 mantissa = -signedMantissa;
86 sign = 1;
87 } else {
88 mantissa = +signedMantissa;
89 sign = 0;
90 }
91
92 /*
93 * Generate reduced precision mantissa.
94 */
95 if (fracExp.exponent > 0)
96 mantissa <<= fracExp.exponent;
97 else
98 mantissa >>= -fracExp.exponent;
99
100 mantissa >>= (23 - rpfP->mantissa_bits - 1);
101
102 mantissa += 1; /* Round last bit. */
103 mantissa >>= 1;
104
105 if (mantissa == 0) /* close to zero */
106 return RPF_ZERO;
107 else if (mantissa >= (1U << rpfP->mantissa_bits)) /* overflow */
108 return sign;
109 else
110 return ((mantissa & ((1U << rpfP->mantissa_bits) - 1)) << 1) | sign;
111 }
112
113
114
115 float
btor(int const binary,const rpf_t * const rpfP)116 btor (int const binary,
117 const rpf_t * const rpfP)
118 /*
119 * Convert value 'binary' in reduced precision format to a real value.
120 * For more information refer to function rtob() above.
121 *
122 * Return value:
123 * converted value
124 */
125 {
126 unsigned int mantissa;
127 float sign;
128 float f;
129
130 if (binary == RPF_ZERO)
131 return 0;
132
133 if (binary < 0 || binary >= 1 << (rpfP->mantissa_bits + 1))
134 error ("Reduced precision format: value %d out of range.", binary);
135
136 /*
137 * Restore IEEE float format:
138 * mantissa (23 Bits), exponent (8 Bits) and sign (1 Bit)
139 */
140
141 sign = (binary & 0x1) == 0 ? 1.0 : -1.0;
142 mantissa = (binary & ((0x1 << (rpfP->mantissa_bits + 1)) - 1)) >> 1;
143 mantissa <<= (23 - rpfP->mantissa_bits);
144
145 if (mantissa == 0)
146 f = sign;
147 else
148 f = sign * (float) mantissa / 8388608;
149
150 return f * rpfP->range; /* expand [ -1 ; +1 ] to
151 [ -range ; +range ] */
152 }
153
154
155
156
157 rpf_t *
alloc_rpf(unsigned const mantissa,fiasco_rpf_range_e const range)158 alloc_rpf (unsigned const mantissa,
159 fiasco_rpf_range_e const range)
160 /*
161 * Reduced precision format constructor.
162 * Allocate memory for the rpf_t structure.
163 * Number of mantissa bits is given by `mantissa'.
164 * The range of the real values is in the interval [-`range', +`range'].
165 * In case of invalid parameters, a structure with default values is
166 * returned.
167 *
168 * Return value
169 * pointer to the new rpf structure
170 */
171 {
172 rpf_t * rpfP;
173
174 MALLOCVAR(rpfP);
175
176 if (mantissa < 2) {
177 warning (_("Size of RPF mantissa has to be in the interval [2,8]. "
178 "Using minimum value 2.\n"));
179 rpfP->mantissa_bits = 2;
180 } else if (mantissa > 8) {
181 warning (_("Size of RPF mantissa has to be in the interval [2,8]. "
182 "Using maximum value 8.\n"));
183 rpfP->mantissa_bits = 2;
184 } else
185 rpfP->mantissa_bits = mantissa;
186
187 switch (range) {
188 case FIASCO_RPF_RANGE_0_75:
189 rpfP->range = 0.75;
190 rpfP->range_e = range;
191 break;
192 case FIASCO_RPF_RANGE_1_50:
193 rpfP->range = 1.50;
194 rpfP->range_e = range;
195 break;
196 case FIASCO_RPF_RANGE_2_00:
197 rpfP->range = 2.00;
198 rpfP->range_e = range;
199 break;
200 case FIASCO_RPF_RANGE_1_00:
201 rpfP->range = 1.00;
202 rpfP->range_e = range;
203 break;
204 default:
205 warning (_("Invalid RPF range specified. Using default value 1.0."));
206 rpfP->range = 1.00;
207 rpfP->range_e = FIASCO_RPF_RANGE_1_00;
208 break;
209 }
210 return rpfP;
211 }
212
213