// Copyright 2002, 2004 David Hilvert , // /* This file is part of the Anti-Lamenessing Engine. The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. The Anti-Lamenessing Engine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the Anti-Lamenessing Engine; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __ale_real_h__ #define __ale_real_h__ #include "ale_fixed.h" #define SINGLE 1 #define DOUBLE 2 #define HALF 3 #define FIXED32 4 #define FIXED16 5 #define ale_real_enable_casting() #define ale_real_disable_casting() #define ale_real_unexceptional_negation(VALUE) -(VALUE) #define ale_real_from_int(INT_VALUE, MAXVAL) (((float) (INT_VALUE)) / ((float) (MAXVAL))) #define ale_real_to_int(REAL_VALUE, MAXVAL) round((float) (REAL_VALUE) * (MAXVAL)) #define ale_real_weight_floor 0.0001 /* * Real-valued type used to represent the range of an image (colors, weights, * etc.). * * ale_real is used in computation. * ale_sreal is used for storage. */ #if ALE_COLORS == SINGLE typedef float ale_real; typedef float ale_sreal; #define ale_real_ip_weight_floor 1e-10 #define ale_real_confidence_floor 0.001 #define ALE_REAL_PRECISION_STRING "SINGLE" #elif ALE_COLORS == DOUBLE typedef double ale_real; typedef double ale_sreal; #define ale_real_ip_weight_floor 1e-10 #define ale_real_confidence_floor 0.000001 #define ALE_REAL_PRECISION_STRING "DOUBLE" #elif ALE_COLORS == HALF /* * What follows is one approach to packing a floating point * number into 16 bits. This implementation is very slow. */ #define MANTISSA_BITS (9) #define EXP_BITS (15 - MANTISSA_BITS) #define EXP_SPECIAL (1 << (EXP_BITS - 1)) #define EXP_MAX (EXP_SPECIAL - 1) #define EXP_MIN (-EXP_MAX) typedef float ale_real; class ale_sreal { union { uint16_t bits; struct { uint16_t sign:1; uint16_t mant:MANTISSA_BITS; int16_t exp :EXP_BITS; } fpr; } u; public: ale_sreal() { u.bits = 0; } ale_sreal operator=(float v) { if (v == 0) { u.bits = 0; } else if (isnan(v)) { u.fpr.exp = EXP_SPECIAL; u.fpr.mant = 1; } else { if (v > 0) u.fpr.sign = 0; else if (v < 0) { u.fpr.sign = 1; v = -v; } else assert(0); /* * Get the exponent. */ int log2 = (int) floor (log(v) / log(2)); /* * Test the exponent against the largest expressible * exponent for ale_sreal. */ if (log2 > EXP_MAX) { /* * Infinity */ u.fpr.exp = EXP_SPECIAL; u.fpr.mant = 0; return *this; } /* * Test the exponent against the smallest expressible * exponent for ale_sreal. */ if (log2 < EXP_MIN) { /* * Zero */ u.fpr.exp = 0x0; u.fpr.mant = 0; return *this; } /* * The exponent is in range, so use it. */ u.fpr.exp = log2; u.fpr.mant = (uint16_t) floor(v / pow(2, log2) * (1 << (MANTISSA_BITS - 1))); } return *this; } operator float() const { float result = 3.14159; if (((uint16_t) u.fpr.exp == EXP_SPECIAL) && (u.fpr.mant == 1)) { /* * NaN */ float a = 0; float b = 0; result = a / b; } else if (((uint16_t) u.fpr.exp == EXP_SPECIAL) && (u.fpr.mant == 0)) { /* * Infinity */ float a = 1; float b = 0; result = (a / b); } else if ((uint16_t) u.fpr.exp != EXP_SPECIAL) { /* * Value is finite. */ result = u.fpr.mant / ((double) (1 << (MANTISSA_BITS - 1))) * pow(2, u.fpr.exp); } else assert(0); if (u.fpr.sign) result = -result; return result; } ale_sreal operator-=(float r) { *this = (float) *this - (float) r; return *this; } ale_sreal operator/=(float r) { *this = (float) *this / (float) r; return *this; } ale_sreal operator*=(float r) { *this = (float) *this * (float) r; return *this; } ale_sreal operator+=(float r) { *this = (float) *this + (float) r; return *this; } }; #undef MANTISSA_BITS #undef EXP_BITS #undef EXP_SPECIAL #undef EXP_MAX #undef EXP_MIN #define ALE_REAL_PRECISION_STRING "HALF" #elif ALE_COLORS == FIXED32 typedef ale_fixed ale_real; typedef ale_fixed ale_sreal; #undef ale_real_enable_casting #undef ale_real_disable_casting #define ale_real_enable_casting() ale_real::enable_casting() #define ale_real_disable_casting() ale_real::disable_casting() #undef ale_real_unexceptional_negation #define ale_real_unexceptional_negation(VALUE) (VALUE).unexceptional_negation(); #undef ale_real_to_int #undef ale_real_from_int #define ale_real_to_int(REAL_VALUE, MAXVAL) ( (MAXVAL == 255) \ ? (int) ale_fixed::fixed_to_bits(REAL_VALUE) \ : ( (MAXVAL == 65535) \ ? (int) ale_fixed::fixed_to_bits(REAL_VALUE) \ : (int) round((float) (REAL_VALUE) * (MAXVAL)) ) ) #define ale_real_from_int(INT_VALUE, MAXVAL) ( (MAXVAL == 255) \ ? (ale_real) ale_fixed::bits_to_fixed(INT_VALUE) \ : ( (MAXVAL == 65535) \ ? (ale_real) ale_fixed::bits_to_fixed(INT_VALUE) \ : (ale_real) (((float) (INT_VALUE)) / ((float) (MAXVAL))) ) ) #define ale_real_ip_weight_floor (1 / (ale_real) 100) #define ale_real_confidence_floor (1 / (ale_real) 10) #define ALE_REAL_PRECISION_STRING "FIXED32" #elif ALE_COLORS == FIXED16 typedef ale_fixed ale_real; typedef ale_fixed ale_sreal; #undef ale_real_enable_casting #undef ale_real_disable_casting #define ale_real_enable_casting() ale_real::enable_casting() #define ale_real_disable_casting() ale_real::disable_casting() #undef ale_real_unexceptional_negation #define ale_real_unexceptional_negation(VALUE) (VALUE).unexceptional_negation(); #undef ale_real_to_int #undef ale_real_from_int #define ale_real_to_int(REAL_VALUE, MAXVAL) ( (MAXVAL == 255) \ ? (int) ale_fixed::fixed_to_bits(REAL_VALUE) \ : ( (MAXVAL == 65535) \ ? (int) ale_fixed::fixed_to_bits(REAL_VALUE) \ : (int) round((float) (REAL_VALUE) * (MAXVAL)) ) ) #define ale_real_from_int(INT_VALUE, MAXVAL) ( (MAXVAL == 255) \ ? (ale_real) ale_fixed::bits_to_fixed(INT_VALUE) \ : ( (MAXVAL == 65535) \ ? (ale_real) ale_fixed::bits_to_fixed(INT_VALUE) \ : (ale_real) (((float) (INT_VALUE)) / ((float) (MAXVAL))) ) ) #define ale_real_ip_weight_floor (1 / (ale_real) 100) #define ale_real_confidence_floor (1 / (ale_real) 10) #define ALE_REAL_PRECISION_STRING "FIXED16" #else #warning Unknown precision in ale_real.h: Choosing PRECISION=SINGLE. typedef float ale_real; typedef float ale_sreal; #define ale_real_ip_weight_floor 1e-10 #define ale_real_confidence_floor 0.001 #define ALE_REAL_PRECISION_STRING "SINGLE" #endif const ale_real ale_real_0 = (ale_real) 0; #undef SINGLE #undef DOUBLE #undef HALF #undef FIXED16 #undef FIXED32 #endif