d2::combine::get_image_dynamic(): Use lrintf() instead of floor() and ceil().
[Ale.git] / ale_real.h
blobce9bc7458af1f71eec43ec38429b4fab346b92f4
1 // Copyright 2002, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
2 // <dhilvert@ugcs.caltech.edu>
4 /* This file is part of the Anti-Lamenessing Engine.
6 The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with the Anti-Lamenessing Engine; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #ifndef __ale_real_h__
22 #define __ale_real_h__
24 #define SINGLE 1
25 #define DOUBLE 2
26 #define HALF 3
29 * Real-valued type used to represent the range of an image (colors, weights,
30 * etc.).
32 * ale_real is used in computation.
33 * ale_sreal is used for storage.
36 #if ALE_COLORS == SINGLE
38 typedef float ale_real;
39 typedef float ale_sreal;
41 #define ALE_REAL_PRECISION_STRING "SINGLE"
43 #elif ALE_COLORS == DOUBLE
45 typedef double ale_real;
46 typedef double ale_sreal;
48 #define ALE_REAL_PRECISION_STRING "DOUBLE"
50 #elif ALE_COLORS == HALF
53 * What follows is one approach to packing a floating point
54 * number into 16 bits. This implementation is very slow.
57 #define MANTISSA_BITS (9)
58 #define EXP_BITS (15 - MANTISSA_BITS)
59 #define EXP_SPECIAL (1 << (EXP_BITS - 1))
60 #define EXP_MAX (EXP_SPECIAL - 1)
61 #define EXP_MIN (-EXP_MAX)
63 typedef float ale_real;
65 class ale_sreal {
67 union {
68 uint16_t bits;
69 struct {
70 uint16_t sign:1;
71 uint16_t mant:MANTISSA_BITS;
72 int16_t exp :EXP_BITS;
73 } fpr;
74 } u;
75 public:
76 ale_sreal() {
77 u.bits = 0;
79 ale_sreal operator=(float v) {
80 if (v == 0) {
81 u.bits = 0;
82 } else if (isnan(v)) {
83 u.fpr.exp = EXP_SPECIAL;
84 u.fpr.mant = 1;
85 } else {
87 if (v > 0)
88 u.fpr.sign = 0;
89 else if (v < 0) {
90 u.fpr.sign = 1;
91 v = -v;
92 } else
93 assert(0);
96 * Get the exponent.
99 int log2 = (int) floor (log(v) / log(2));
102 * Test the exponent against the largest expressible
103 * exponent for ale_sreal.
106 if (log2 > EXP_MAX) {
108 * Infinity
111 u.fpr.exp = EXP_SPECIAL;
112 u.fpr.mant = 0;
114 return *this;
118 * Test the exponent against the smallest expressible
119 * exponent for ale_sreal.
122 if (log2 < EXP_MIN) {
124 * Zero
127 u.fpr.exp = 0x0;
128 u.fpr.mant = 0;
130 return *this;
134 * The exponent is in range, so use it.
137 u.fpr.exp = log2;
139 u.fpr.mant = (uint16_t) floor(v / pow(2, log2) * (1 << (MANTISSA_BITS - 1)));
142 return *this;
145 operator float() const {
146 float result = 3.14159;
148 if (((uint16_t) u.fpr.exp == EXP_SPECIAL) && (u.fpr.mant == 1)) {
151 * NaN
154 float a = 0;
155 float b = 0;
157 result = a / b;
159 } else if (((uint16_t) u.fpr.exp == EXP_SPECIAL) && (u.fpr.mant == 0)) {
162 * Infinity
165 float a = 1;
166 float b = 0;
168 result = (a / b);
170 } else if ((uint16_t) u.fpr.exp != EXP_SPECIAL) {
173 * Value is finite.
176 result = u.fpr.mant / ((double) (1 << (MANTISSA_BITS - 1)))
177 * pow(2, u.fpr.exp);
179 } else
180 assert(0);
182 if (u.fpr.sign)
183 result = -result;
185 return result;
188 ale_sreal operator-=(float r) {
189 *this = (float) *this - (float) r;
190 return *this;
192 ale_sreal operator/=(float r) {
193 *this = (float) *this / (float) r;
194 return *this;
196 ale_sreal operator*=(float r) {
197 *this = (float) *this * (float) r;
198 return *this;
200 ale_sreal operator+=(float r) {
201 *this = (float) *this + (float) r;
202 return *this;
206 #undef MANTISSA_BITS
207 #undef EXP_BITS
208 #undef EXP_SPECIAL
209 #undef EXP_MAX
210 #undef EXP_MIN
212 #define ALE_REAL_PRECISION_STRING "HALF"
214 #else
216 #warning Unknown precision in ale_real.h: Choosing PRECISION=SINGLE.
218 typedef float ale_real;
219 typedef float ale_sreal;
221 #define ALE_REAL_PRECISION_STRING "SINGLE"
223 #endif
225 #undef SINGLE
226 #undef DOUBLE
227 #undef HALF
229 #endif