bugs: Consider alternatives to refiltering following Irani-Peleg.
[Ale.git] / ale_real.h
blob09d61f8f509951e3c4d6f1ae9ccb5ed95e3a43f5
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 #include "ale_fixed.h"
26 #define SINGLE 1
27 #define DOUBLE 2
28 #define HALF 3
29 #define FIXED32 4
30 #define FIXED16 5
32 #define ale_real_enable_casting()
33 #define ale_real_disable_casting()
35 #define ale_real_unexceptional_negation(VALUE) -(VALUE)
37 #define ale_real_from_int(INT_VALUE, MAXVAL) (((float) (INT_VALUE)) / ((float) (MAXVAL)))
38 #define ale_real_to_int(REAL_VALUE, MAXVAL) round((float) (REAL_VALUE) * (MAXVAL))
39 #define ale_real_weight_floor 0.0001
42 * Real-valued type used to represent the range of an image (colors, weights,
43 * etc.).
45 * ale_real is used in computation.
46 * ale_sreal is used for storage.
49 #if ALE_COLORS == SINGLE
51 typedef float ale_real;
52 typedef float ale_sreal;
54 #define ale_real_ip_weight_floor 1e-10
55 #define ale_real_confidence_floor 0.001
57 #define ALE_REAL_PRECISION_STRING "SINGLE"
59 #elif ALE_COLORS == DOUBLE
61 typedef double ale_real;
62 typedef double ale_sreal;
64 #define ale_real_ip_weight_floor 1e-10
65 #define ale_real_confidence_floor 0.000001
67 #define ALE_REAL_PRECISION_STRING "DOUBLE"
69 #elif ALE_COLORS == HALF
72 * What follows is one approach to packing a floating point
73 * number into 16 bits. This implementation is very slow.
76 #define MANTISSA_BITS (9)
77 #define EXP_BITS (15 - MANTISSA_BITS)
78 #define EXP_SPECIAL (1 << (EXP_BITS - 1))
79 #define EXP_MAX (EXP_SPECIAL - 1)
80 #define EXP_MIN (-EXP_MAX)
82 typedef float ale_real;
84 class ale_sreal {
86 union {
87 uint16_t bits;
88 struct {
89 uint16_t sign:1;
90 uint16_t mant:MANTISSA_BITS;
91 int16_t exp :EXP_BITS;
92 } fpr;
93 } u;
94 public:
95 ale_sreal() {
96 u.bits = 0;
98 ale_sreal operator=(float v) {
99 if (v == 0) {
100 u.bits = 0;
101 } else if (isnan(v)) {
102 u.fpr.exp = EXP_SPECIAL;
103 u.fpr.mant = 1;
104 } else {
106 if (v > 0)
107 u.fpr.sign = 0;
108 else if (v < 0) {
109 u.fpr.sign = 1;
110 v = -v;
111 } else
112 assert(0);
115 * Get the exponent.
118 int log2 = (int) floor (log(v) / log(2));
121 * Test the exponent against the largest expressible
122 * exponent for ale_sreal.
125 if (log2 > EXP_MAX) {
127 * Infinity
130 u.fpr.exp = EXP_SPECIAL;
131 u.fpr.mant = 0;
133 return *this;
137 * Test the exponent against the smallest expressible
138 * exponent for ale_sreal.
141 if (log2 < EXP_MIN) {
143 * Zero
146 u.fpr.exp = 0x0;
147 u.fpr.mant = 0;
149 return *this;
153 * The exponent is in range, so use it.
156 u.fpr.exp = log2;
158 u.fpr.mant = (uint16_t) floor(v / pow(2, log2) * (1 << (MANTISSA_BITS - 1)));
161 return *this;
164 operator float() const {
165 float result = 3.14159;
167 if (((uint16_t) u.fpr.exp == EXP_SPECIAL) && (u.fpr.mant == 1)) {
170 * NaN
173 float a = 0;
174 float b = 0;
176 result = a / b;
178 } else if (((uint16_t) u.fpr.exp == EXP_SPECIAL) && (u.fpr.mant == 0)) {
181 * Infinity
184 float a = 1;
185 float b = 0;
187 result = (a / b);
189 } else if ((uint16_t) u.fpr.exp != EXP_SPECIAL) {
192 * Value is finite.
195 result = u.fpr.mant / ((double) (1 << (MANTISSA_BITS - 1)))
196 * pow(2, u.fpr.exp);
198 } else
199 assert(0);
201 if (u.fpr.sign)
202 result = -result;
204 return result;
207 ale_sreal operator-=(float r) {
208 *this = (float) *this - (float) r;
209 return *this;
211 ale_sreal operator/=(float r) {
212 *this = (float) *this / (float) r;
213 return *this;
215 ale_sreal operator*=(float r) {
216 *this = (float) *this * (float) r;
217 return *this;
219 ale_sreal operator+=(float r) {
220 *this = (float) *this + (float) r;
221 return *this;
225 #undef MANTISSA_BITS
226 #undef EXP_BITS
227 #undef EXP_SPECIAL
228 #undef EXP_MAX
229 #undef EXP_MIN
231 #define ALE_REAL_PRECISION_STRING "HALF"
233 #elif ALE_COLORS == FIXED32
235 typedef ale_fixed<ale_fixed_32,16> ale_real;
236 typedef ale_fixed<ale_fixed_32,16> ale_sreal;
238 #undef ale_real_enable_casting
239 #undef ale_real_disable_casting
240 #define ale_real_enable_casting() ale_real::enable_casting()
241 #define ale_real_disable_casting() ale_real::disable_casting()
243 #undef ale_real_unexceptional_negation
244 #define ale_real_unexceptional_negation(VALUE) (VALUE).unexceptional_negation();
246 #undef ale_real_to_int
247 #undef ale_real_from_int
248 #define ale_real_to_int(REAL_VALUE, MAXVAL) ( (MAXVAL == 255) \
249 ? (int) ale_fixed<ale_fixed_16_calc,8>::fixed_to_bits(REAL_VALUE) \
250 : ( (MAXVAL == 65535) \
251 ? (int) ale_fixed<ale_fixed_16_calc,16>::fixed_to_bits(REAL_VALUE) \
252 : (int) round((float) (REAL_VALUE) * (MAXVAL)) ) )
254 #define ale_real_from_int(INT_VALUE, MAXVAL) ( (MAXVAL == 255) \
255 ? (ale_real) ale_fixed<ale_fixed_16_calc,8>::bits_to_fixed(INT_VALUE) \
256 : ( (MAXVAL == 65535) \
257 ? (ale_real) ale_fixed<ale_fixed_16_calc,16>::bits_to_fixed(INT_VALUE) \
258 : (ale_real) (((float) (INT_VALUE)) / ((float) (MAXVAL))) ) )
260 #define ale_real_ip_weight_floor (1 / (ale_real) 100)
261 #define ale_real_confidence_floor (1 / (ale_real) 10)
263 #define ALE_REAL_PRECISION_STRING "FIXED32"
265 #elif ALE_COLORS == FIXED16
267 typedef ale_fixed<ale_fixed_16_calc,14> ale_real;
268 typedef ale_fixed<ale_fixed_16,12> ale_sreal;
270 #undef ale_real_enable_casting
271 #undef ale_real_disable_casting
272 #define ale_real_enable_casting() ale_real::enable_casting()
273 #define ale_real_disable_casting() ale_real::disable_casting()
275 #undef ale_real_unexceptional_negation
276 #define ale_real_unexceptional_negation(VALUE) (VALUE).unexceptional_negation();
278 #undef ale_real_to_int
279 #undef ale_real_from_int
280 #define ale_real_to_int(REAL_VALUE, MAXVAL) ( (MAXVAL == 255) \
281 ? (int) ale_fixed<ale_fixed_16_calc,8>::fixed_to_bits(REAL_VALUE) \
282 : ( (MAXVAL == 65535) \
283 ? (int) ale_fixed<ale_fixed_16_calc,16>::fixed_to_bits(REAL_VALUE) \
284 : (int) round((float) (REAL_VALUE) * (MAXVAL)) ) )
286 #define ale_real_from_int(INT_VALUE, MAXVAL) ( (MAXVAL == 255) \
287 ? (ale_real) ale_fixed<ale_fixed_16_calc,8>::bits_to_fixed(INT_VALUE) \
288 : ( (MAXVAL == 65535) \
289 ? (ale_real) ale_fixed<ale_fixed_16_calc,16>::bits_to_fixed(INT_VALUE) \
290 : (ale_real) (((float) (INT_VALUE)) / ((float) (MAXVAL))) ) )
292 #define ale_real_ip_weight_floor (1 / (ale_real) 100)
293 #define ale_real_confidence_floor (1 / (ale_real) 10)
295 #define ALE_REAL_PRECISION_STRING "FIXED16"
297 #else
299 #warning Unknown precision in ale_real.h: Choosing PRECISION=SINGLE.
301 typedef float ale_real;
302 typedef float ale_sreal;
304 #define ale_real_ip_weight_floor 1e-10
305 #define ale_real_confidence_floor 0.001
307 #define ALE_REAL_PRECISION_STRING "SINGLE"
309 #endif
311 const ale_real ale_real_0 = (ale_real) 0;
313 #undef SINGLE
314 #undef DOUBLE
315 #undef HALF
316 #undef FIXED16
317 #undef FIXED32
319 #endif