diff options
Diffstat (limited to 'indra/llmath/llmath.h')
-rw-r--r-- | indra/llmath/llmath.h | 162 |
1 files changed, 111 insertions, 51 deletions
diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h index 6df241d3ab..798f1154d0 100644 --- a/indra/llmath/llmath.h +++ b/indra/llmath/llmath.h @@ -2,38 +2,45 @@ * @file llmath.h * @brief Useful math constants and macros. * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2007, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception + * This library 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 + * Lesser General Public License for more details. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #ifndef LLMATH_H #define LLMATH_H +#include <cmath> +#include <cstdlib> +#include <complex> +#include "lldefs.h" +//#include "llstl.h" // *TODO: Remove when LLString is gone +//#include "llstring.h" // *TODO: Remove when LLString is gone +// lltut.h uses is_approx_equal_fraction(). This was moved to its own header +// file in llcommon so we can use lltut.h for llcommon tests without making +// llcommon depend on llmath. +#include "is_approx_equal_fraction.h" + // work around for Windows & older gcc non-standard function names. #if LL_WINDOWS +#include <float.h> #define llisnan(val) _isnan(val) #define llfinite(val) _finite(val) #elif (LL_LINUX && __GNUC__ <= 2) @@ -48,11 +55,11 @@ #endif // Single Precision Floating Point Routines -#ifndef fsqrtf -#define fsqrtf(x) ((F32)sqrt((F64)(x))) -#endif #ifndef sqrtf -#define sqrtf(x) ((F32)sqrt((F64)(x))) +#define sqrtf(x) ((F32)sqrt((F64)(x))) +#endif +#ifndef fsqrtf +#define fsqrtf(x) sqrtf(x) #endif #ifndef cosf @@ -65,11 +72,14 @@ #define tanf(x) ((F32)tan((F64)(x))) #endif #ifndef acosf -#define acosf(x) ((F32)acos((F64)(x))) +#define acosf(x) ((F32)acos((F64)(x))) #endif #ifndef powf -#define powf(x,y) ((F32)pow((F64)(x),(F64)(y))) +#define powf(x,y) ((F32)pow((F64)(x),(F64)(y))) +#endif +#ifndef expf +#define expf(x) ((F32)exp((F64)(x))) #endif const F32 GRAVITY = -9.8f; @@ -78,6 +88,8 @@ const F32 GRAVITY = -9.8f; const F32 F_PI = 3.1415926535897932384626433832795f; const F32 F_TWO_PI = 6.283185307179586476925286766559f; const F32 F_PI_BY_TWO = 1.5707963267948966192313216916398f; +const F32 F_SQRT_TWO_PI = 2.506628274631000502415765284811f; +const F32 F_E = 2.71828182845904523536f; const F32 F_SQRT2 = 1.4142135623730950488016887242097f; const F32 F_SQRT3 = 1.73205080756888288657986402541f; const F32 OO_SQRT2 = 0.7071067811865475244008443621049f; @@ -87,52 +99,64 @@ const F32 F_APPROXIMATELY_ZERO = 0.00001f; const F32 F_LN2 = 0.69314718056f; const F32 OO_LN2 = 1.4426950408889634073599246810019f; +const F32 F_ALMOST_ZERO = 0.0001f; +const F32 F_ALMOST_ONE = 1.0f - F_ALMOST_ZERO; + // BUG: Eliminate in favor of F_APPROXIMATELY_ZERO above? const F32 FP_MAG_THRESHOLD = 0.0000001f; // TODO: Replace with logic like is_approx_equal inline BOOL is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < F_APPROXIMATELY_ZERO); } +// These functions work by interpreting sign+exp+mantissa as an unsigned +// integer. +// For example: +// x = <sign>1 <exponent>00000010 <mantissa>00000000000000000000000 +// y = <sign>1 <exponent>00000001 <mantissa>11111111111111111111111 +// +// interpreted as ints = +// x = 10000001000000000000000000000000 +// y = 10000000111111111111111111111111 +// which is clearly a different of 1 in the least significant bit +// Values with the same exponent can be trivially shown to work. +// +// WARNING: Denormals of opposite sign do not work +// x = <sign>1 <exponent>00000000 <mantissa>00000000000000000000001 +// y = <sign>0 <exponent>00000000 <mantissa>00000000000000000000001 +// Although these values differ by 2 in the LSB, the sign bit makes +// the int comparison fail. +// +// WARNING: NaNs can compare equal +// There is no special treatment of exceptional values like NaNs +// +// WARNING: Infinity is comparable with F32_MAX and negative +// infinity is comparable with F32_MIN + inline BOOL is_approx_equal(F32 x, F32 y) { const S32 COMPARE_MANTISSA_UP_TO_BIT = 0x02; - return (abs((S32) ((U32&)x - (U32&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); + return (std::abs((S32) ((U32&)x - (U32&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); } -inline BOOL is_approx_equal_fraction(F32 x, F32 y, U32 frac_bits) +inline BOOL is_approx_equal(F64 x, F64 y) { - BOOL ret = TRUE; - F32 diff = (F32) fabs(x - y); - - S32 diffInt = (S32) diff; - S32 diffFracTolerance = (S32) ((diff - (F32) diffInt) * (1 << frac_bits)); - - // if integer portion is not equal, not enough bits were used for packing - // so error out since either the use case is not correct OR there is - // an issue with pack/unpack. should fail in either case. - // for decimal portion, make sure that the delta is no more than 1 - // based on the number of bits used for packing decimal portion. - if (diffInt != 0 || diffFracTolerance > 1) - { - ret = FALSE; - } - - return ret; + const S64 COMPARE_MANTISSA_UP_TO_BIT = 0x02; + return (std::abs((S32) ((U64&)x - (U64&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); } inline S32 llabs(const S32 a) { - return S32(labs(a)); + return S32(std::labs(a)); } inline F32 llabs(const F32 a) { - return F32(fabs(a)); + return F32(std::fabs(a)); } inline F64 llabs(const F64 a) { - return F64(fabs(a)); + return F64(std::fabs(a)); } inline S32 lltrunc( F32 f ) @@ -176,7 +200,7 @@ inline S32 llfloor( F32 f ) } return result; #else - return (S32)floor(f); + return (S32)floorf(f); #endif } @@ -440,8 +464,8 @@ inline F32 llsimple_angle(F32 angle) return angle; } -//calculate the nearesr power of two number for val, bounded by max_power_two -inline U32 get_nearest_power_two(U32 val, U32 max_power_two) +//SDK - Renamed this to get_lower_power_two, since this is what this actually does. +inline U32 get_lower_power_two(U32 val, U32 max_power_two) { if(!max_power_two) { @@ -456,4 +480,40 @@ inline U32 get_nearest_power_two(U32 val, U32 max_power_two) return max_power_two ; } + +// calculate next highest power of two, limited by max_power_two +// This is taken from a brilliant little code snipped on http://acius2.blogspot.com/2007/11/calculating-next-power-of-2.html +// Basically we convert the binary to a solid string of 1's with the same +// number of digits, then add one. We subtract 1 initially to handle +// the case where the number passed in is actually a power of two. +// WARNING: this only works with 32 bit ints. +inline U32 get_next_power_two(U32 val, U32 max_power_two) +{ + if(!max_power_two) + { + max_power_two = 1 << 31 ; + } + + if(val >= max_power_two) + { + return max_power_two; + } + + val--; + val = (val >> 1) | val; + val = (val >> 2) | val; + val = (val >> 4) | val; + val = (val >> 8) | val; + val = (val >> 16) | val; + val++; + + return val; +} + +//get the gaussian value given the linear distance from axis x and guassian value o +inline F32 llgaussian(F32 x, F32 o) +{ + return 1.f/(F_SQRT_TWO_PI*o)*powf(F_E, -(x*x)/(2*o*o)); +} + #endif |