Gnash  0.8.10
GnashNumeric.h
Go to the documentation of this file.
00001 // GnashNumeric.h: vaguely useful mathematical functions.
00002 // 
00003 //   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
00004 //   Free Software Foundation, Inc
00005 // 
00006 // This program is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU General Public License as published by
00008 // the Free Software Foundation; either version 3 of the License, or
00009 // (at your option) any later version.
00010 // 
00011 // This program is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 // 
00016 // You should have received a copy of the GNU General Public License
00017 // along with this program; if not, write to the Free Software
00018 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019 //
00020 
00021 #ifndef GNASH_NUMERIC_H
00022 #define GNASH_NUMERIC_H
00023 
00024 #ifdef HAVE_CONFIG_H
00025 # include "gnashconfig.h"
00026 #endif
00027 
00028 #ifdef SOLARIS_HOST
00029 # include <ieeefp.h> // for finite()
00030 #endif
00031 
00032 #include <cassert>
00033 #include <cmath>
00034 #include <algorithm>
00035 #include <boost/cstdint.hpp>
00036 #include <limits>
00037 #include <boost/utility/enable_if.hpp>
00038 
00039 namespace gnash {
00040 
00041 // Using a possible built-in pi constant M_PI, which is not in
00042 // the C++ standard, has no greate advantage, so we will use this
00043 // one. Make it as accurate as you like.
00044 static const double PI = 3.14159265358979323846;
00045 
00046 inline bool
00047 isFinite(double d)
00048 {
00049 #if defined(HAVE_FINITE) && !defined(HAVE_ISFINITE)
00050     return (finite(d));
00051 #else
00052     // Put using namespace std; here if you have to
00053     // put it anywhere.
00054     using namespace std;
00055     return (isfinite(d));
00056 #endif
00057 }
00058 
00059 inline double
00060 infinite_to_zero(double x)
00061 {
00062     return isFinite(x) ? x : 0.0;
00063 }
00064 
00065 template <typename T>
00066 inline T
00067 clamp(T i, T min, T max)
00068 {
00069         assert(min <= max);
00070         return std::max<T>(min, std::min<T>(i, max));
00071 }
00072 
00073 template<typename T>
00074 inline T
00075 lerp(T a, T b, T f)
00076 {
00077     return (b - a) * f + a;
00078 }
00079 
00080 inline int
00081 frnd(float f) 
00082 {
00083     return static_cast<int>(f + 0.5f);
00084 }
00085 
00086 inline double
00087 twipsToPixels(int i) 
00088 { 
00089     return static_cast<double>(i / 20.0); 
00090 }
00091 
00092 template<size_t Factor>
00093 boost::int32_t
00094 truncateWithFactor(double a)
00095 { 
00096 
00097     const double factor = static_cast<double>(Factor);
00098 
00099     // This truncates large values without relying on undefined behaviour.
00100     // For very large values of 'a' it is noticeably slower than the UB
00101     // version (due to fmod), but should always be legal behaviour. For
00102     // ordinary values (within ±1.07374e+08 pixels) it is comparable to
00103     // the UB version for speed. Because values outside the limit are
00104     // extremely rare, using this safe version has no implications for
00105     // performance under normal circumstances.
00106     static const double upperUnsignedLimit =
00107                 std::numeric_limits<boost::uint32_t>::max() + 1.0;
00108     static const double upperSignedLimit =
00109                 std::numeric_limits<boost::int32_t>::max() / factor;
00110     static const double lowerSignedLimit =
00111                 std::numeric_limits<boost::int32_t>::min() / factor;
00112 
00113     if (a >= lowerSignedLimit && a <= upperSignedLimit) {
00114         return a * Factor;
00115     }
00116 
00117     // This slow truncation happens only in very unlikely cases.
00118     return a >= 0 ?
00119         static_cast<boost::uint32_t>(
00120                 std::fmod(a * factor, upperUnsignedLimit))
00121         : 
00122         -static_cast<boost::uint32_t>(
00123                 std::fmod(-a * factor, upperUnsignedLimit));
00124 }
00125 
00126 // truncate when overflow occurs.
00127 inline boost::int32_t
00128 pixelsToTwips(double a)
00129 {
00130     return truncateWithFactor<20>(a);
00131 }
00132 
00133 } // namespace gnash
00134 
00135 #endif