515 lines
12 KiB
C++
515 lines
12 KiB
C++
// Copyright 2007 Georgia Institute of Technology. All rights reserved.
|
|
// ABSOLUTELY NOT FOR DISTRIBUTION
|
|
/**
|
|
* @file math.h
|
|
*
|
|
* Includes all basic FASTlib non-vector math utilities.
|
|
*/
|
|
|
|
#ifndef MATH_MATH_H
|
|
#define MATH_MATH_H
|
|
|
|
#include "base/base.h"
|
|
|
|
#include <math.h>
|
|
|
|
/**
|
|
* Math routines.
|
|
*
|
|
* The hope is that this should contain most of the useful math routines
|
|
* you can think of. Currently, this is very sparse.
|
|
*/
|
|
namespace math {
|
|
/** The square root of 2. */
|
|
const double SQRT2 = 1.41421356237309504880;
|
|
/** Base of the natural logarithm. */
|
|
const double E = 2.7182818284590452354;
|
|
/** Log base 2 of E. */
|
|
const double LOG2_E = 1.4426950408889634074;
|
|
/** Log base 10 of E. */
|
|
const double LOG10_E = 0.43429448190325182765;
|
|
/** Natural log of 2. */
|
|
const double LN_2 = 0.69314718055994530942;
|
|
/** Natural log of 10. */
|
|
const double LN_10 = 2.30258509299404568402;
|
|
/** The ratio of the circumference of a circle to its diameter. */
|
|
const double PI = 3.141592653589793238462643383279;
|
|
/** The ratio of the circumference of a circle to its radius. */
|
|
const double PI_2 = 1.57079632679489661923;
|
|
|
|
/** Squares a number. */
|
|
template<typename T>
|
|
inline T Sqr(T v) {
|
|
return v * v;
|
|
}
|
|
|
|
/**
|
|
* Rounds a double-precision to an integer, casting it too.
|
|
*/
|
|
inline int64 RoundInt(double d) {
|
|
return int64(nearbyint(d));
|
|
}
|
|
|
|
/**
|
|
* Forces a number to be non-negative, turning negative numbers into zero.
|
|
*
|
|
* Avoids branching costs (yes, we've discovered measurable improvements).
|
|
*/
|
|
inline double ClampNonNegative(double d) {
|
|
return (d + fabs(d)) / 2;
|
|
}
|
|
|
|
/**
|
|
* Forces a number to be non-positive, turning positive numbers into zero.
|
|
*
|
|
* Avoids branching costs (yes, we've discovered measurable improvements).
|
|
*/
|
|
inline double ClampNonPositive(double d) {
|
|
return (d - fabs(d)) / 2;
|
|
}
|
|
|
|
/**
|
|
* Clips a number between a particular range.
|
|
*
|
|
* @param value the number to clip
|
|
* @param range_min the first of the range
|
|
* @param range_max the last of the range
|
|
* @return max(range_min, min(range_max, d))
|
|
*/
|
|
inline double ClampRange(double value, double range_min, double range_max) {
|
|
if (unlikely(value <= range_min)) {
|
|
return range_min;
|
|
} else if (unlikely(value >= range_max)) {
|
|
return range_max;
|
|
} else {
|
|
return value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generates a uniform random number between 0 and 1.
|
|
*/
|
|
inline double Random() {
|
|
return rand() * (1.0 / RAND_MAX);
|
|
}
|
|
|
|
/**
|
|
* Generates a uniform random number in the specified range.
|
|
*/
|
|
inline double Random(double lo, double hi) {
|
|
return Random() * (hi - lo) + lo;
|
|
}
|
|
|
|
/**
|
|
* Generates a uniform random integer.
|
|
*/
|
|
inline int RandInt(int hi_exclusive) {
|
|
return rand() % hi_exclusive;
|
|
}
|
|
/**
|
|
* Generates a uniform random integer.
|
|
*/
|
|
inline int RandInt(int lo, int hi_exclusive) {
|
|
return (rand() % (hi_exclusive - lo)) + lo;
|
|
}
|
|
};
|
|
|
|
#include "math_impl.h"
|
|
|
|
namespace math {
|
|
/**
|
|
* Calculates a relatively small power using template metaprogramming.
|
|
*
|
|
* This allows a numerator and denominator. In the case where the
|
|
* numerator and denominator are equal, this will not do anything, or in
|
|
* the case where the denominator is one.
|
|
*/
|
|
template<int t_numerator, int t_denominator>
|
|
inline double Pow(double d) {
|
|
return math__private::ZPowImpl<t_numerator, t_denominator>::Calculate(d);
|
|
}
|
|
|
|
/**
|
|
* Calculates a small power of the absolute value of a number
|
|
* using template metaprogramming.
|
|
*
|
|
* This allows a numerator and denominator. In the case where the
|
|
* numerator and denominator are equal, this will not do anything, or in
|
|
* the case where the denominator is one. For even powers, this will
|
|
* avoid calling the absolute value function.
|
|
*/
|
|
template<int t_numerator, int t_denominator>
|
|
inline double PowAbs(double d) {
|
|
// we specify whether it's an even function -- if so, we can sometimes
|
|
// avoid the absolute value sign
|
|
return math__private::ZPowAbsImpl<t_numerator, t_denominator,
|
|
(t_numerator%t_denominator == 0) && ((t_numerator/t_denominator)%2 == 0)>::Calculate(fabs(d));
|
|
}
|
|
};
|
|
|
|
/**
|
|
* A value which is the min or max of multiple other values.
|
|
*
|
|
* Comes with a highly optimized version of x = max(x, y).
|
|
*
|
|
* The template argument should be something like double, with greater-than,
|
|
* less-than, and equals operators.
|
|
*/
|
|
template<typename TValue>
|
|
class MinMaxVal {
|
|
public:
|
|
typedef TValue Value;
|
|
|
|
public:
|
|
/** The underlying value. */
|
|
Value val;
|
|
|
|
OT_DEF_BASIC(MinMaxVal) {
|
|
OT_MY_OBJECT(val);
|
|
}
|
|
|
|
public:
|
|
/**
|
|
* Converts implicitly to the value.
|
|
*/
|
|
operator Value() const { return val; }
|
|
|
|
/**
|
|
* Sets the value.
|
|
*/
|
|
const Value& operator = (Value val_in) {
|
|
return (val = val_in);
|
|
}
|
|
|
|
/**
|
|
* Efficiently performs this->val = min(this->val, incoming_val).
|
|
*
|
|
* The expectation is that it is higly unlikely for the incoming
|
|
* value to be the new minimum.
|
|
*/
|
|
void MinWith(Value incoming_val) {
|
|
if (unlikely(incoming_val < val)) {
|
|
val = incoming_val;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Efficiently performs this->val = min(this->val, incoming_val).
|
|
*
|
|
* The expectation is that it is higly unlikely for the incoming
|
|
* value to be the new maximum.
|
|
*/
|
|
void MaxWith(Value incoming_val) {
|
|
if (unlikely(incoming_val > val)) {
|
|
val = incoming_val;
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Simple real-valued range.
|
|
*
|
|
* @experimental
|
|
*/
|
|
struct DRange {
|
|
public:
|
|
/**
|
|
* The lower bound.
|
|
*/
|
|
double lo;
|
|
/**
|
|
* The upper bound.
|
|
*/
|
|
double hi;
|
|
|
|
OT_DEF_BASIC(DRange) {
|
|
OT_MY_OBJECT(lo);
|
|
OT_MY_OBJECT(hi);
|
|
}
|
|
|
|
public:
|
|
/** Initializes to specified values. */
|
|
DRange(double lo_in, double hi_in)
|
|
: lo(lo_in), hi(hi_in)
|
|
{}
|
|
|
|
/** Initialize to an empty set, where lo > hi. */
|
|
void InitEmptySet() {
|
|
lo = DBL_MAX;
|
|
hi = -DBL_MAX;
|
|
}
|
|
|
|
/** Initializes to -infinity to infinity. */
|
|
void InitUniversalSet() {
|
|
lo = -DBL_MAX;
|
|
hi = DBL_MAX;
|
|
}
|
|
|
|
/** Initializes to a range of values. */
|
|
void Init(double lo_in, double hi_in) {
|
|
lo = lo_in;
|
|
hi = hi_in;
|
|
}
|
|
|
|
/**
|
|
* Resets to a range of values.
|
|
*
|
|
* Since there is no dynamic memory this is the same as Init, but calling
|
|
* Reset instead of Init probably looks more similar to surrounding code.
|
|
*/
|
|
void Reset(double lo_in, double hi_in) {
|
|
lo = lo_in;
|
|
hi = hi_in;
|
|
}
|
|
|
|
/**
|
|
* Gets the span of the range, hi - lo.
|
|
*/
|
|
double width() const {
|
|
return hi - lo;
|
|
}
|
|
|
|
/**
|
|
* Gets the midpoint of this range.
|
|
*/
|
|
double mid() const {
|
|
return (hi + lo) / 2;
|
|
}
|
|
|
|
/**
|
|
* Interpolates (factor) * hi + (1 - factor) * lo.
|
|
*/
|
|
double interpolate(double factor) const {
|
|
return factor * width() + lo;
|
|
}
|
|
|
|
/**
|
|
* Simulate an union by growing the range if necessary.
|
|
*/
|
|
const DRange& operator |= (double d) {
|
|
if (unlikely(d < lo)) {
|
|
lo = d;
|
|
}
|
|
if (unlikely(d > hi)) {
|
|
hi = d;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Sets this range to include only the specified value, or
|
|
* becomes an empty set if the range does not contain the number.
|
|
*/
|
|
const DRange& operator &= (double d) {
|
|
if (likely(d > lo)) {
|
|
lo = d;
|
|
}
|
|
if (likely(d < hi)) {
|
|
hi = d;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Expands range to include the other range.
|
|
*/
|
|
const DRange& operator |= (const DRange& other) {
|
|
if (unlikely(other.lo < lo)) {
|
|
lo = other.lo;
|
|
}
|
|
if (unlikely(other.hi > hi)) {
|
|
hi = other.hi;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Shrinks range to be the overlap with another range, becoming an empty
|
|
* set if there is no overlap.
|
|
*/
|
|
const DRange& operator &= (const DRange& other) {
|
|
if (unlikely(other.lo > lo)) {
|
|
lo = other.lo;
|
|
}
|
|
if (unlikely(other.hi < hi)) {
|
|
hi = other.hi;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/** Scales upper and lower bounds. */
|
|
friend DRange operator - (const DRange& r) {
|
|
return DRange(-r.hi, -r.lo);
|
|
}
|
|
|
|
/** Scales upper and lower bounds. */
|
|
const DRange& operator *= (double d) {
|
|
DEBUG_ASSERT_MSG(d >= 0, "don't multiply DRanges by negatives, explicitly negate");
|
|
lo *= d;
|
|
hi *= d;
|
|
return *this;
|
|
}
|
|
|
|
/** Scales upper and lower bounds. */
|
|
friend DRange operator * (const DRange& r, double d) {
|
|
DEBUG_ASSERT_MSG(d >= 0, "don't multiply DRanges by negatives, explicitly negate");
|
|
return DRange(r.lo * d, r.hi * d);
|
|
}
|
|
|
|
/** Scales upper and lower bounds. */
|
|
friend DRange operator * (double d, const DRange& r) {
|
|
DEBUG_ASSERT_MSG(d >= 0, "don't multiply DRanges by negatives, explicitly negate");
|
|
return DRange(r.lo * d, r.hi * d);
|
|
}
|
|
|
|
/** Sums the upper and lower independently. */
|
|
const DRange& operator += (const DRange& other) {
|
|
lo += other.lo;
|
|
hi += other.hi;
|
|
return *this;
|
|
}
|
|
|
|
/** Subtracts from the upper and lower.
|
|
* THIS SWAPS THE ORDER OF HI AND LO, assuming a worst case result.
|
|
* This is NOT an undo of the + operator.
|
|
*/
|
|
const DRange& operator -= (const DRange& other) {
|
|
lo -= other.hi;
|
|
hi -= other.lo;
|
|
return *this;
|
|
}
|
|
|
|
/** Adds to the upper and lower independently. */
|
|
const DRange& operator += (double d) {
|
|
lo += d;
|
|
hi += d;
|
|
return *this;
|
|
}
|
|
|
|
/** Subtracts from the upper and lower independently. */
|
|
const DRange& operator -= (double d) {
|
|
lo -= d;
|
|
hi -= d;
|
|
return *this;
|
|
}
|
|
|
|
friend DRange operator + (const DRange& a, const DRange& b) {
|
|
DRange result;
|
|
result.lo = a.lo + b.lo;
|
|
result.hi = a.hi + b.hi;
|
|
return result;
|
|
}
|
|
|
|
friend DRange operator - (const DRange& a, const DRange& b) {
|
|
DRange result;
|
|
result.lo = a.lo - b.hi;
|
|
result.hi = a.hi - b.lo;
|
|
return result;
|
|
}
|
|
|
|
friend DRange operator + (const DRange& a, double b) {
|
|
DRange result;
|
|
result.lo = a.lo + b;
|
|
result.hi = a.hi + b;
|
|
return result;
|
|
}
|
|
|
|
friend DRange operator - (const DRange& a, double b) {
|
|
DRange result;
|
|
result.lo = a.lo - b;
|
|
result.hi = a.hi - b;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Takes the maximum of upper and lower bounds independently.
|
|
*/
|
|
void MaxWith(const DRange& range) {
|
|
if (unlikely(range.lo > lo)) {
|
|
lo = range.lo;
|
|
}
|
|
if (unlikely(range.hi > hi)) {
|
|
hi = range.hi;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Takes the minimum of upper and lower bounds independently.
|
|
*/
|
|
void MinWith(const DRange& range) {
|
|
if (unlikely(range.lo < lo)) {
|
|
lo = range.lo;
|
|
}
|
|
if (unlikely(range.hi < hi)) {
|
|
hi = range.hi;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Takes the maximum of upper and lower bounds independently.
|
|
*/
|
|
void MaxWith(double v) {
|
|
if (unlikely(v > lo)) {
|
|
lo = v;
|
|
if (unlikely(v > hi)) {
|
|
hi = v;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Takes the minimum of upper and lower bounds independently.
|
|
*/
|
|
void MinWith(double v) {
|
|
if (unlikely(v < hi)) {
|
|
hi = v;
|
|
if (unlikely(v < lo)) {
|
|
lo = v;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Compares if this is STRICTLY less than another range.
|
|
*/
|
|
friend bool operator < (const DRange& a, const DRange& b) {
|
|
return a.hi < b.lo;
|
|
}
|
|
EXPAND_LESS_THAN(DRange);
|
|
/**
|
|
* Compares if this is STRICTLY equal to another range.
|
|
*/
|
|
friend bool operator == (const DRange& a, const DRange& b) {
|
|
return a.lo == b.lo && a.hi == b.hi;
|
|
}
|
|
EXPAND_EQUALS(DRange);
|
|
|
|
/**
|
|
* Compares if this is STRICTLY less than a value.
|
|
*/
|
|
friend bool operator < (const DRange& a, double b) {
|
|
return a.hi < b;
|
|
}
|
|
EXPAND_HETERO_LESS_THAN(DRange, double);
|
|
/**
|
|
* Compares if a value is STRICTLY less than this range.
|
|
*/
|
|
friend bool operator < (double a, const DRange& b) {
|
|
return a < b.lo;
|
|
}
|
|
EXPAND_HETERO_LESS_THAN(double, DRange);
|
|
|
|
/**
|
|
* Determines if a point is contained within the range.
|
|
*/
|
|
bool Contains(double d) const {
|
|
return d >= lo || d <= hi;
|
|
}
|
|
};
|
|
|
|
#include "discrete.h"
|
|
#include "kernel.h"
|
|
#include "geometry.h"
|
|
|
|
#endif
|