From e9a458a7a56705bf546be8d86ccc32af14cd5bff Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Wed, 12 Dec 2007 16:57:12 +0000 Subject: [PATCH] Split the global math functions out of NumTraits.h --- src/Core.h | 1 + src/Core/MathFunctions.h | 175 +++++++++++++++++++++++++++++++++++++++ src/Core/NumTraits.h | 146 -------------------------------- 3 files changed, 176 insertions(+), 146 deletions(-) create mode 100644 src/Core/MathFunctions.h diff --git a/src/Core.h b/src/Core.h index cfa67bd3a..068b46bce 100644 --- a/src/Core.h +++ b/src/Core.h @@ -6,6 +6,7 @@ namespace Eigen { #include "Core/Util.h" #include "Core/NumTraits.h" +#include "Core/MathFunctions.h" #include "Core/MatrixBase.h" #include "Core/OperatorEquals.h" #include "Core/MatrixRef.h" diff --git a/src/Core/MathFunctions.h b/src/Core/MathFunctions.h new file mode 100644 index 000000000..0647e943f --- /dev/null +++ b/src/Core/MathFunctions.h @@ -0,0 +1,175 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. Eigen itself is part of the KDE project. +// +// Copyright (C) 2006-2007 Benoit Jacob +// +// Eigen 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 2 or (at your option) any later version. +// +// Eigen 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 Eigen; if not, write to the Free Software Foundation, Inc., 51 +// Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. This exception does not invalidate any other reasons why a work +// based on this file might be covered by the GNU General Public License. + +#ifndef EIGEN_MATHFUNCTIONS_H +#define EIGEN_MATHFUNCTIONS_H + +template inline typename NumTraits::Real precision(); +template inline T random(T a, T b); +template inline T random(); + +template<> inline int precision() { return 0; } +inline int real(int x) { return x; } +inline int imag(int) { return 0; } +inline int conj(int x) { return x; } +inline int abs(int x) { return std::abs(x); } +inline int abs2(int x) { return x*x; } +inline int sqrt(int) +{ + // Taking the square root of integers is not allowed + // (the square root does not always exist within the integers). + // Please cast to a floating-point type. + assert(false); + return 0; +} +template<> inline int random(int a, int b) +{ + // We can't just do rand()%n as only the high-order bits are really random + return a + static_cast((b-a+1) * (rand() / (RAND_MAX + 1.0))); +} +template<> inline int random() +{ + return random(-10, 10); +} +inline bool isMuchSmallerThan(int a, int, int = precision()) +{ + return a == 0; +} +inline bool isApprox(int a, int b, int = precision()) +{ + return a == b; +} +inline bool isApproxOrLessThan(int a, int b, int = precision()) +{ + return a <= b; +} + +template<> inline float precision() { return 1e-5f; } +inline float real(float x) { return x; } +inline float imag(float) { return 0.f; } +inline float conj(float x) { return x; } +inline float abs(float x) { return std::abs(x); } +inline float abs2(float x) { return x*x; } +inline float sqrt(float x) { return std::sqrt(x); } +template<> inline float random(float a, float b) +{ + return a + (b-a) * std::rand() / RAND_MAX; +} +template<> inline float random() +{ + return random(-10.0f, 10.0f); +} +inline bool isMuchSmallerThan(float a, float b, float prec = precision()) +{ + return std::abs(a) <= std::abs(b) * prec; +} +inline bool isApprox(float a, float b, float prec = precision()) +{ + return std::abs(a - b) <= std::min(std::abs(a), std::abs(b)) * prec; +} +inline bool isApproxOrLessThan(float a, float b, float prec = precision()) +{ + return a <= b || isApprox(a, b, prec); +} + +template<> inline double precision() { return 1e-11; } +inline double real(double x) { return x; } +inline double imag(double) { return 0.; } +inline double conj(double x) { return x; } +inline double abs(double x) { return std::abs(x); } +inline double abs2(double x) { return x*x; } +inline double sqrt(double x) { return std::sqrt(x); } +template<> inline double random(double a, double b) +{ + return a + (b-a) * std::rand() / RAND_MAX; +} +template<> inline double random() +{ + return random(-10.0, 10.0); +} +inline bool isMuchSmallerThan(double a, double b, double prec = precision()) +{ + return std::abs(a) <= std::abs(b) * prec; +} +inline bool isApprox(double a, double b, double prec = precision()) +{ + return std::abs(a - b) <= std::min(std::abs(a), std::abs(b)) * prec; +} +inline bool isApproxOrLessThan(double a, double b, double prec = precision()) +{ + return a <= b || isApprox(a, b, prec); +} + +template<> inline float precision >() { return precision(); } +inline float real(const std::complex& x) { return std::real(x); } +inline float imag(const std::complex& x) { return std::imag(x); } +inline std::complex conj(const std::complex& x) { return std::conj(x); } +inline float abs(const std::complex& x) { return std::abs(x); } +inline float abs2(const std::complex& x) { return std::norm(x); } +inline std::complex sqrt(const std::complex&) +{ + // Taking the square roots of complex numbers is not allowed, + // as this is ambiguous (there are two square roots). + // What were you trying to do? + assert(false); + return 0; +} +template<> inline std::complex random() +{ + return std::complex(random(), random()); +} +inline bool isMuchSmallerThan(const std::complex& a, const std::complex& b, float prec = precision()) +{ + return abs2(a) <= abs2(b) * prec * prec; +} +inline bool isApprox(const std::complex& a, const std::complex& b, float prec = precision()) +{ + return isApprox(std::real(a), std::real(b), prec) + && isApprox(std::imag(a), std::imag(b), prec); +} +// isApproxOrLessThan wouldn't make sense for complex numbers + +template<> inline double precision >() { return precision(); } +inline double real(const std::complex& x) { return std::real(x); } +inline double imag(const std::complex& x) { return std::imag(x); } +inline std::complex conj(const std::complex& x) { return std::conj(x); } +inline double abs(const std::complex& x) { return std::abs(x); } +inline double abs2(const std::complex& x) { return std::norm(x); } +template<> inline std::complex random() +{ + return std::complex(random(), random()); +} +inline bool isMuchSmallerThan(const std::complex& a, const std::complex& b, double prec = precision()) +{ + return abs2(a) <= abs2(b) * prec * prec; +} +inline bool isApprox(const std::complex& a, const std::complex& b, double prec = precision()) +{ + return isApprox(std::real(a), std::real(b), prec) + && isApprox(std::imag(a), std::imag(b), prec); +} +// isApproxOrLessThan wouldn't make sense for complex numbers + +#endif // EIGEN_MATHFUNCTIONS_H diff --git a/src/Core/NumTraits.h b/src/Core/NumTraits.h index c6ce06a97..9269fbcdc 100644 --- a/src/Core/NumTraits.h +++ b/src/Core/NumTraits.h @@ -56,150 +56,4 @@ template struct NumTraits > static const bool HasFloatingPoint = NumTraits::HasFloatingPoint; }; -template inline typename NumTraits::Real precision(); -template inline T random(T a, T b); -template inline T random(); - -template<> inline int precision() { return 0; } -inline int real(int x) { return x; } -inline int imag(int) { return 0; } -inline int conj(int x) { return x; } -inline int abs(int x) { return std::abs(x); } -inline int abs2(int x) { return x*x; } -inline int sqrt(int) -{ - // Taking the square root of integers is not allowed - // (the square root does not always exist within the integers). - // Please cast to a floating-point type. - assert(false); - return 0; -} -template<> inline int random(int a, int b) -{ - // We can't just do rand()%n as only the high-order bits are really random - return a + static_cast((b-a+1) * (rand() / (RAND_MAX + 1.0))); -} -template<> inline int random() -{ - return random(-10, 10); -} -inline bool isMuchSmallerThan(int a, int, int = precision()) -{ - return a == 0; -} -inline bool isApprox(int a, int b, int = precision()) -{ - return a == b; -} -inline bool isApproxOrLessThan(int a, int b, int = precision()) -{ - return a <= b; -} - -template<> inline float precision() { return 1e-5f; } -inline float real(float x) { return x; } -inline float imag(float) { return 0.f; } -inline float conj(float x) { return x; } -inline float abs(float x) { return std::abs(x); } -inline float abs2(float x) { return x*x; } -inline float sqrt(float x) { return std::sqrt(x); } -template<> inline float random(float a, float b) -{ - return a + (b-a) * std::rand() / RAND_MAX; -} -template<> inline float random() -{ - return random(-10.0f, 10.0f); -} -inline bool isMuchSmallerThan(float a, float b, float prec = precision()) -{ - return std::abs(a) <= std::abs(b) * prec; -} -inline bool isApprox(float a, float b, float prec = precision()) -{ - return std::abs(a - b) <= std::min(std::abs(a), std::abs(b)) * prec; -} -inline bool isApproxOrLessThan(float a, float b, float prec = precision()) -{ - return a <= b || isApprox(a, b, prec); -} - -template<> inline double precision() { return 1e-11; } -inline double real(double x) { return x; } -inline double imag(double) { return 0.; } -inline double conj(double x) { return x; } -inline double abs(double x) { return std::abs(x); } -inline double abs2(double x) { return x*x; } -inline double sqrt(double x) { return std::sqrt(x); } -template<> inline double random(double a, double b) -{ - return a + (b-a) * std::rand() / RAND_MAX; -} -template<> inline double random() -{ - return random(-10.0, 10.0); -} -inline bool isMuchSmallerThan(double a, double b, double prec = precision()) -{ - return std::abs(a) <= std::abs(b) * prec; -} -inline bool isApprox(double a, double b, double prec = precision()) -{ - return std::abs(a - b) <= std::min(std::abs(a), std::abs(b)) * prec; -} -inline bool isApproxOrLessThan(double a, double b, double prec = precision()) -{ - return a <= b || isApprox(a, b, prec); -} - -template<> inline float precision >() { return precision(); } -inline float real(const std::complex& x) { return std::real(x); } -inline float imag(const std::complex& x) { return std::imag(x); } -inline std::complex conj(const std::complex& x) { return std::conj(x); } -inline float abs(const std::complex& x) { return std::abs(x); } -inline float abs2(const std::complex& x) { return std::norm(x); } -inline std::complex sqrt(const std::complex&) -{ - // Taking the square roots of complex numbers is not allowed, - // as this is ambiguous (there are two square roots). - // What were you trying to do? - assert(false); - return 0; -} -template<> inline std::complex random() -{ - return std::complex(random(), random()); -} -inline bool isMuchSmallerThan(const std::complex& a, const std::complex& b, float prec = precision()) -{ - return abs2(a) <= abs2(b) * prec * prec; -} -inline bool isApprox(const std::complex& a, const std::complex& b, float prec = precision()) -{ - return isApprox(std::real(a), std::real(b), prec) - && isApprox(std::imag(a), std::imag(b), prec); -} -// isApproxOrLessThan wouldn't make sense for complex numbers - -template<> inline double precision >() { return precision(); } -inline double real(const std::complex& x) { return std::real(x); } -inline double imag(const std::complex& x) { return std::imag(x); } -inline std::complex conj(const std::complex& x) { return std::conj(x); } -inline double abs(const std::complex& x) { return std::abs(x); } -inline double abs2(const std::complex& x) { return std::norm(x); } -template<> inline std::complex random() -{ - return std::complex(random(), random()); -} -inline bool isMuchSmallerThan(const std::complex& a, const std::complex& b, double prec = precision()) -{ - return abs2(a) <= abs2(b) * prec * prec; -} -inline bool isApprox(const std::complex& a, const std::complex& b, double prec = precision()) -{ - return isApprox(std::real(a), std::real(b), prec) - && isApprox(std::imag(a), std::imag(b), prec); -} -// isApproxOrLessThan wouldn't make sense for complex numbers - #endif // EIGEN_NUMTRAITS_H