Squashed 'src/beast/' content from commit 43e6d34

git-subtree-dir: src/beast
git-subtree-split: 43e6d345e4
This commit is contained in:
Vinnie Falco
2013-09-11 09:57:14 -07:00
commit 86ba8ffca6
487 changed files with 263286 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,322 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_BIGINTEGER_H_INCLUDED
#define BEAST_BIGINTEGER_H_INCLUDED
//==============================================================================
/**
An arbitrarily large integer class.
A BigInteger can be used in a similar way to a normal integer, but has no size
limit (except for memory and performance constraints).
Negative values are possible, but the value isn't stored as 2s-complement, so
be careful if you use negative values and look at the values of individual bits.
*/
class BEAST_API BigInteger : LeakChecked <BigInteger>
{
public:
//==============================================================================
/** Creates an empty BigInteger */
BigInteger();
/** Creates a BigInteger containing an integer value in its low bits.
The low 32 bits of the number are initialised with this value.
*/
BigInteger (uint32 value);
/** Creates a BigInteger containing an integer value in its low bits.
The low 32 bits of the number are initialised with the absolute value
passed in, and its sign is set to reflect the sign of the number.
*/
BigInteger (int32 value);
/** Creates a BigInteger containing an integer value in its low bits.
The low 64 bits of the number are initialised with the absolute value
passed in, and its sign is set to reflect the sign of the number.
*/
BigInteger (int64 value);
/** Creates a copy of another BigInteger. */
BigInteger (const BigInteger& other);
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
BigInteger (BigInteger&& other) noexcept;
BigInteger& operator= (BigInteger&& other) noexcept;
#endif
/** Destructor. */
~BigInteger();
//==============================================================================
/** Copies another BigInteger onto this one. */
BigInteger& operator= (const BigInteger& other);
/** Swaps the internal contents of this with another object. */
void swapWith (BigInteger& other) noexcept;
//==============================================================================
/** Returns the value of a specified bit in the number.
If the index is out-of-range, the result will be false.
*/
bool operator[] (int bit) const noexcept;
/** Returns true if no bits are set. */
bool isZero() const noexcept;
/** Returns true if the value is 1. */
bool isOne() const noexcept;
/** Attempts to get the lowest bits of the value as an integer.
If the value is bigger than the integer limits, this will return only the lower bits.
*/
int toInteger() const noexcept;
//==============================================================================
/** Resets the value to 0. */
void clear();
/** Clears a particular bit in the number. */
void clearBit (int bitNumber) noexcept;
/** Sets a specified bit to 1. */
void setBit (int bitNumber);
/** Sets or clears a specified bit. */
void setBit (int bitNumber, bool shouldBeSet);
/** Sets a range of bits to be either on or off.
@param startBit the first bit to change
@param numBits the number of bits to change
@param shouldBeSet whether to turn these bits on or off
*/
void setRange (int startBit, int numBits, bool shouldBeSet);
/** Inserts a bit an a given position, shifting up any bits above it. */
void insertBit (int bitNumber, bool shouldBeSet);
/** Returns a range of bits as a new BigInteger.
e.g. getBitRangeAsInt (0, 64) would return the lowest 64 bits.
@see getBitRangeAsInt
*/
BigInteger getBitRange (int startBit, int numBits) const;
/** Returns a range of bits as an integer value.
e.g. getBitRangeAsInt (0, 32) would return the lowest 32 bits.
Asking for more than 32 bits isn't allowed (obviously) - for that, use
getBitRange().
*/
uint32 getBitRangeAsInt (int startBit, int numBits) const noexcept;
/** Sets a range of bits to an integer value.
Copies the given integer onto a range of bits, starting at startBit,
and using up to numBits of the available bits.
*/
void setBitRangeAsInt (int startBit, int numBits, uint32 valueToSet);
/** Shifts a section of bits left or right.
@param howManyBitsLeft how far to move the bits (+ve numbers shift it left, -ve numbers shift it right).
@param startBit the first bit to affect - if this is > 0, only bits above that index will be affected.
*/
void shiftBits (int howManyBitsLeft, int startBit);
/** Returns the total number of set bits in the value. */
int countNumberOfSetBits() const noexcept;
/** Looks for the index of the next set bit after a given starting point.
This searches from startIndex (inclusive) upwards for the first set bit,
and returns its index. If no set bits are found, it returns -1.
*/
int findNextSetBit (int startIndex) const noexcept;
/** Looks for the index of the next clear bit after a given starting point.
This searches from startIndex (inclusive) upwards for the first clear bit,
and returns its index.
*/
int findNextClearBit (int startIndex) const noexcept;
/** Returns the index of the highest set bit in the number.
If the value is zero, this will return -1.
*/
int getHighestBit() const noexcept;
//==============================================================================
// All the standard arithmetic ops...
BigInteger& operator+= (const BigInteger& other);
BigInteger& operator-= (const BigInteger& other);
BigInteger& operator*= (const BigInteger& other);
BigInteger& operator/= (const BigInteger& other);
BigInteger& operator|= (const BigInteger& other);
BigInteger& operator&= (const BigInteger& other);
BigInteger& operator^= (const BigInteger& other);
BigInteger& operator%= (const BigInteger& other);
BigInteger& operator<<= (int numBitsToShift);
BigInteger& operator>>= (int numBitsToShift);
BigInteger& operator++();
BigInteger& operator--();
BigInteger operator++ (int);
BigInteger operator-- (int);
BigInteger operator-() const;
BigInteger operator+ (const BigInteger& other) const;
BigInteger operator- (const BigInteger& other) const;
BigInteger operator* (const BigInteger& other) const;
BigInteger operator/ (const BigInteger& other) const;
BigInteger operator| (const BigInteger& other) const;
BigInteger operator& (const BigInteger& other) const;
BigInteger operator^ (const BigInteger& other) const;
BigInteger operator% (const BigInteger& other) const;
BigInteger operator<< (int numBitsToShift) const;
BigInteger operator>> (int numBitsToShift) const;
bool operator== (const BigInteger& other) const noexcept;
bool operator!= (const BigInteger& other) const noexcept;
bool operator< (const BigInteger& other) const noexcept;
bool operator<= (const BigInteger& other) const noexcept;
bool operator> (const BigInteger& other) const noexcept;
bool operator>= (const BigInteger& other) const noexcept;
//==============================================================================
/** Does a signed comparison of two BigIntegers.
Return values are:
- 0 if the numbers are the same
- < 0 if this number is smaller than the other
- > 0 if this number is bigger than the other
*/
int compare (const BigInteger& other) const noexcept;
/** Compares the magnitudes of two BigIntegers, ignoring their signs.
Return values are:
- 0 if the numbers are the same
- < 0 if this number is smaller than the other
- > 0 if this number is bigger than the other
*/
int compareAbsolute (const BigInteger& other) const noexcept;
/** Divides this value by another one and returns the remainder.
This number is divided by other, leaving the quotient in this number,
with the remainder being copied to the other BigInteger passed in.
*/
void divideBy (const BigInteger& divisor, BigInteger& remainder);
/** Returns the largest value that will divide both this value and the one passed-in.
*/
BigInteger findGreatestCommonDivisor (BigInteger other) const;
/** Performs a combined exponent and modulo operation.
This BigInteger's value becomes (this ^ exponent) % modulus.
*/
void exponentModulo (const BigInteger& exponent, const BigInteger& modulus);
/** Performs an inverse modulo on the value.
i.e. the result is (this ^ -1) mod (modulus).
*/
void inverseModulo (const BigInteger& modulus);
//==============================================================================
/** Returns true if the value is less than zero.
@see setNegative, negate
*/
bool isNegative() const noexcept;
/** Changes the sign of the number to be positive or negative.
@see isNegative, negate
*/
void setNegative (bool shouldBeNegative) noexcept;
/** Inverts the sign of the number.
@see isNegative, setNegative
*/
void negate() noexcept;
//==============================================================================
/** Converts the number to a string.
Specify a base such as 2 (binary), 8 (octal), 10 (decimal), 16 (hex).
If minimumNumCharacters is greater than 0, the returned string will be
padded with leading zeros to reach at least that length.
*/
String toString (int base, int minimumNumCharacters = 1) const;
/** Reads the numeric value from a string.
Specify a base such as 2 (binary), 8 (octal), 10 (decimal), 16 (hex).
Any invalid characters will be ignored.
*/
void parseString (const String& text, int base);
//==============================================================================
/** Turns the number into a block of binary data.
The data is arranged as little-endian, so the first byte of data is the low 8 bits
of the number, and so on.
@see loadFromMemoryBlock
*/
MemoryBlock toMemoryBlock() const;
/** Converts a block of raw data into a number.
The data is arranged as little-endian, so the first byte of data is the low 8 bits
of the number, and so on.
@see toMemoryBlock
*/
void loadFromMemoryBlock (const MemoryBlock& data);
private:
//==============================================================================
HeapBlock <uint32> values;
size_t numValues;
int highestBit;
bool negative;
void ensureSize (size_t numVals);
void shiftLeft (int bits, int startBit);
void shiftRight (int bits, int startBit);
};
/** Writes a BigInteger to an OutputStream as a UTF8 decimal string. */
OutputStream& BEAST_CALLTYPE operator<< (OutputStream& stream, const BigInteger& value);
//==============================================================================
#ifndef DOXYGEN
// For backwards compatibility, BitArray is defined as an alias for BigInteger.
typedef BigInteger BitArray;
#endif
#endif // BEAST_BIGINTEGER_H_INCLUDED

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,264 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_EXPRESSION_H_INCLUDED
#define BEAST_EXPRESSION_H_INCLUDED
//==============================================================================
/**
A class for dynamically evaluating simple numeric expressions.
This class can parse a simple C-style string expression involving floating point
numbers, named symbols and functions. The basic arithmetic operations of +, -, *, /
are supported, as well as parentheses, and any alphanumeric identifiers are
assumed to be named symbols which will be resolved when the expression is
evaluated.
Expressions which use identifiers and functions require a subclass of
Expression::Scope to be supplied when evaluating them, and this object
is expected to be able to resolve the symbol names and perform the functions that
are used.
*/
class BEAST_API Expression
{
public:
//==============================================================================
/** Creates a simple expression with a value of 0. */
Expression();
/** Destructor. */
~Expression();
/** Creates a simple expression with a specified constant value. */
explicit Expression (double constant);
/** Creates a copy of an expression. */
Expression (const Expression& other);
/** Copies another expression. */
Expression& operator= (const Expression& other);
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
Expression (Expression&& other) noexcept;
Expression& operator= (Expression&& other) noexcept;
#endif
/** Creates an expression by parsing a string.
If there's a syntax error in the string, this will throw a ParseError exception.
@throws ParseError
*/
explicit Expression (const String& stringToParse);
/** Returns a string version of the expression. */
String toString() const;
/** Returns an expression which is an addtion operation of two existing expressions. */
Expression operator+ (const Expression& other) const;
/** Returns an expression which is a subtraction operation of two existing expressions. */
Expression operator- (const Expression& other) const;
/** Returns an expression which is a multiplication operation of two existing expressions. */
Expression operator* (const Expression& other) const;
/** Returns an expression which is a division operation of two existing expressions. */
Expression operator/ (const Expression& other) const;
/** Returns an expression which performs a negation operation on an existing expression. */
Expression operator-() const;
/** Returns an Expression which is an identifier reference. */
static Expression symbol (const String& symbol);
/** Returns an Expression which is a function call. */
static Expression function (const String& functionName, const Array<Expression>& parameters);
/** Returns an Expression which parses a string from a character pointer, and updates the pointer
to indicate where it finished.
The pointer is incremented so that on return, it indicates the character that follows
the end of the expression that was parsed.
If there's a syntax error in the string, this will throw a ParseError exception.
@throws ParseError
*/
static Expression parse (String::CharPointerType& stringToParse);
//==============================================================================
/** When evaluating an Expression object, this class is used to resolve symbols and
perform functions that the expression uses.
*/
class BEAST_API Scope
{
public:
Scope();
virtual ~Scope();
/** Returns some kind of globally unique ID that identifies this scope. */
virtual String getScopeUID() const;
/** Returns the value of a symbol.
If the symbol is unknown, this can throw an Expression::EvaluationError exception.
The member value is set to the part of the symbol that followed the dot, if there is
one, e.g. for "foo.bar", symbol = "foo" and member = "bar".
@throws Expression::EvaluationError
*/
virtual Expression getSymbolValue (const String& symbol) const;
/** Executes a named function.
If the function name is unknown, this can throw an Expression::EvaluationError exception.
@throws Expression::EvaluationError
*/
virtual double evaluateFunction (const String& functionName,
const double* parameters, int numParameters) const;
/** Used as a callback by the Scope::visitRelativeScope() method.
You should never create an instance of this class yourself, it's used by the
expression evaluation code.
*/
class Visitor
{
public:
virtual ~Visitor() {}
virtual void visit (const Scope&) = 0;
};
/** Creates a Scope object for a named scope, and then calls a visitor
to do some kind of processing with this new scope.
If the name is valid, this method must create a suitable (temporary) Scope
object to represent it, and must call the Visitor::visit() method with this
new scope.
*/
virtual void visitRelativeScope (const String& scopeName, Visitor& visitor) const;
};
/** Evaluates this expression, without using a Scope.
Without a Scope, no symbols can be used, and only basic functions such as sin, cos, tan,
min, max are available.
To find out about any errors during evaluation, use the other version of this method which
takes a String parameter.
*/
double evaluate() const;
/** Evaluates this expression, providing a scope that should be able to evaluate any symbols
or functions that it uses.
To find out about any errors during evaluation, use the other version of this method which
takes a String parameter.
*/
double evaluate (const Scope& scope) const;
/** Evaluates this expression, providing a scope that should be able to evaluate any symbols
or functions that it uses.
*/
double evaluate (const Scope& scope, String& evaluationError) const;
/** Attempts to return an expression which is a copy of this one, but with a constant adjusted
to make the expression resolve to a target value.
E.g. if the expression is "x + 10" and x is 5, then asking for a target value of 8 will return
the expression "x + 3". Obviously some expressions can't be reversed in this way, in which
case they might just be adjusted by adding a constant to the original expression.
@throws Expression::EvaluationError
*/
Expression adjustedToGiveNewResult (double targetValue, const Scope& scope) const;
/** Represents a symbol that is used in an Expression. */
struct Symbol
{
Symbol (const String& scopeUID, const String& symbolName);
bool operator== (const Symbol&) const noexcept;
bool operator!= (const Symbol&) const noexcept;
String scopeUID; /**< The unique ID of the Scope that contains this symbol. */
String symbolName; /**< The name of the symbol. */
};
/** Returns a copy of this expression in which all instances of a given symbol have been renamed. */
Expression withRenamedSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope) const;
/** Returns true if this expression makes use of the specified symbol.
If a suitable scope is supplied, the search will dereference and recursively check
all symbols, so that it can be determined whether this expression relies on the given
symbol at any level in its evaluation. If the scope parameter is null, this just checks
whether the expression contains any direct references to the symbol.
@throws Expression::EvaluationError
*/
bool referencesSymbol (const Symbol& symbol, const Scope& scope) const;
/** Returns true if this expression contains any symbols. */
bool usesAnySymbols() const;
/** Returns a list of all symbols that may be needed to resolve this expression in the given scope. */
void findReferencedSymbols (Array<Symbol>& results, const Scope& scope) const;
//==============================================================================
/** An exception that can be thrown by Expression::parse(). */
class ParseError : public std::exception
{
public:
ParseError (const String& message);
String description;
};
//==============================================================================
/** Expression type.
@see Expression::getType()
*/
enum Type
{
constantType,
functionType,
operatorType,
symbolType
};
/** Returns the type of this expression. */
Type getType() const noexcept;
/** If this expression is a symbol, function or operator, this returns its identifier. */
String getSymbolOrFunction() const;
/** Returns the number of inputs to this expression.
@see getInput
*/
int getNumInputs() const;
/** Retrieves one of the inputs to this expression.
@see getNumInputs
*/
Expression getInput (int index) const;
private:
//==============================================================================
class Term;
struct Helpers;
friend class Term;
friend struct Helpers;
friend class ScopedPointer<Term>;
friend class SharedPtr<Term>;
SharedPtr<Term> term;
explicit Expression (Term*);
};
#endif // BEAST_EXPRESSION_H_INCLUDED

View File

@@ -0,0 +1,387 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_INTERVAL_H_INCLUDED
#define BEAST_INTERVAL_H_INCLUDED
/** A half-open interval.
This represents the half-open interval [begin, end) over the scalar
type of template parameter `Ty`. It may also be considered as the
specification of a subset of a 1-dimensional Euclidean space.
@tparam Ty A scalar numerical type.
*/
template <class Ty>
class Interval
{
public:
typedef Ty value_type;
/** The empty interval.
*/
static const Interval none;
/** Create an uninitialized interval.
*/
Interval ()
{
}
/** Create an interval with the specified values.
*/
Interval (Ty begin, Ty end)
: m_begin (begin)
, m_end (end)
{
}
/** Create an interval from another interval.
*/
Interval (Interval const& other)
: m_begin (other.m_begin)
, m_end (other.m_end)
{
}
/** Assign from another interval.
@param other The interval to assign from.
@return A reference to this interval.
*/
Interval& operator= (const Interval& other)
{
m_begin = other.m_begin;
m_end = other.m_end;
return *this;
}
/** Compare an interval for equality.
Empty intervals are always equal to other empty intervals.
@param rhs The other interval to compare.
@return `true` if this interval is equal to the specified interval.
*/
bool operator== (Interval const& rhs) const
{
return (empty () && rhs.empty ()) ||
(m_begin == rhs.m_begin && m_end == rhs.m_end);
}
/** Compare an interval for inequality.
@param rhs The other interval to compare.
@return `true` if this interval is not equal to the specified interval.
*/
bool operator!= (Interval const& rhs) const
{
return !this->operator== (rhs);
}
/** Get the starting value of the interval.
@return The starting point of the interval.
*/
Ty begin () const
{
return m_begin;
}
/** Get the ending value of the interval.
@return The ending point of the interval.
*/
Ty end () const
{
return m_end;
}
/** Get the Lebesque measure.
@return The Lebesque measure.
*/
Ty length () const
{
return empty () ? Ty () : (end () - begin ());
}
//Ty count () const { return length (); } // sugar
//Ty distance () const { return length (); } // sugar
/** Determine if the interval is empty.
@return `true` if the interval is empty.
*/
bool empty () const
{
return m_begin >= m_end;
}
/** Determine if the interval is non-empty.
@return `true` if the interval is not empty.
*/
bool notEmpty () const
{
return m_begin < m_end;
}
/** Set the starting point of the interval.
@param v The starting point.
*/
void setBegin (Ty v)
{
m_begin = v;
}
/** Set the ending point of the interval.
@param v The ending point.
*/
void setEnd (Ty v)
{
m_end = v;
}
/** Set the ending point relative to the starting point.
@param v The length of the resulting interval.
*/
void setLength (Ty v)
{
m_end = m_begin + v;
}
/** Determine if a value is contained in the interval.
@param v The value to check.
@return `true` if this interval contains `v`.
*/
bool contains (Ty v) const
{
return notEmpty () && v >= m_begin && v < m_end;
}
/** Determine if this interval intersects another interval.
@param other The other interval.
@return `true` if the intervals intersect.
*/
template <class To>
bool intersects (Interval <To> const& other) const
{
return notEmpty () && other.notEmpty () &&
end () > other.begin () && begin () < other.end ();
}
/** Determine if this interval adjoins another interval.
An interval is adjoint to another interval if and only if the union of the
intervals is a single non-empty half-open subset.
@param other The other interval.
@return `true` if the intervals are adjoint.
*/
template <class To>
bool adjoins (Interval <To> const& other) const
{
return (empty () != other.empty ()) ||
(notEmpty () && end () >= other.begin ()
&& begin () <= other.end ());
}
/** Determine if this interval is disjoint from another interval.
@param other The other interval.
@return `true` if the intervals are disjoint.
*/
bool disjoint (Interval const& other) const
{
return !intersects (other);
}
/** Determine if this interval is a superset of another interval.
An interval A is a superset of interval B if B is empty or if A fully
contains B.
@param other The other interval.
@return `true` if this is a superset of `other`.
*/
template <class To>
bool superset_of (Interval <To> const& other) const
{
return other.empty () ||
(notEmpty () && begin () <= other.begin ()
&& end () >= other.end ());
}
/** Determine if this interval is a proper superset of another interval.
An interval A is a proper superset of interval B if A is a superset of
B and A is not equal to B.
@param other The other interval.
@return `true` if this interval is a proper superset of `other`.
*/
template <class To>
bool proper_superset_of (Interval <To> const& other) const
{
return this->superset_of (other) && this->operator != (other);
}
/** Determine if this interval is a subset of another interval.
@param other The other interval.
@return `true` if this interval is a subset of `other`.
*/
template <class To>
bool subset_of (Interval <To> const& other) const
{
return other.superset_of (*this);
}
/** Determine if this interval is a proper subset of another interval.
@param other The other interval.
@return `true` if this interval is a proper subset of `other`.
*/
template <class To>
bool proper_subset_of (Interval <To> const& other) const
{
return other.proper_superset_of (*this);
}
/** Return the intersection of this interval with another interval.
@param other The other interval.
@return The intersection of the intervals.
*/
template <class To>
Interval intersection (Interval <To> const& other) const
{
return Interval (std::max (begin (), other.begin ()),
std::min (end (), other.end ()));
}
/** Determine the smallest interval that contains both intervals.
@param other The other interval.
@return The simple union of the intervals.
*/
template <class To>
Interval simple_union (Interval <To> const& other) const
{
return Interval (
std::min (other.normalized ().begin (), normalized ().begin ()),
std::max (other.normalized ().end (), normalized ().end ()));
}
/** Calculate the single-interval union.
The result is empty if the union cannot be represented as a
single half-open interval.
@param other The other interval.
@return The simple union of the intervals.
*/
template <class To>
Interval single_union (Interval <To> const& other) const
{
if (empty ())
return other;
else if (other.empty ())
return *this;
else if (end () < other.begin () || begin () > other.end ())
return none;
else
return Interval (std::min (begin (), other.begin ()),
std::max (end (), other.end ()));
}
/** Determine if the interval is correctly ordered.
@return `true` if the interval is correctly ordered.
*/
bool normal () const
{
return end () >= begin ();
}
/** Return a normalized interval.
@return The normalized interval.
*/
Interval normalized () const
{
if (normal ())
return *this;
else
return Interval (end (), begin ());
}
/** Clamp a value to the interval.
@param v The value to clamp.
@return The clamped result.
*/
template <typename Tv>
Ty clamp (Tv v) const
{
// These conditionals are carefully ordered so
// that if m_begin == m_end, value is assigned m_begin.
if (v > end ())
v = end () - (std::numeric_limits <Tv>::is_integer ? 1 :
std::numeric_limits <Tv>::epsilon ());
if (v < begin ())
v = begin ();
return v;
}
private:
Ty m_begin;
Ty m_end;
};
template <typename Ty>
const Interval<Ty> Interval<Ty>::none = Interval<Ty> (Ty (), Ty ());
#endif

View File

@@ -0,0 +1,84 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_MATH_H_INCLUDED
#define BEAST_MATH_H_INCLUDED
//
// Miscellaneous mathematical calculations
//
// Calculate the bin for a value given the bin size.
// This correctly handles negative numbers. For example
// if value == -1 then calc_bin returns -1.
template <typename Ty>
inline Ty calc_bin (Ty value, int size)
{
if (value >= 0)
return value / size;
else
return (value - size + 1) / size;
}
// Given a number and a bin size, this returns the first
// corresponding value of the bin associated with the given number.
// It correctly handles negative numbers. For example,
// if value == -1 then calc_bin always returns -size
template <typename Ty>
inline Ty calc_bin_start (Ty value, int size)
{
return calc_bin (value, size) * size;
}
template <class T>
inline T pi () noexcept
{
return 3.14159265358979;
}
template <class T>
inline T twoPi () noexcept
{
return 6.28318530717958;
}
template <class T>
inline T oneOverTwoPi () noexcept
{
return 0.1591549430918955;
}
template <class T, class U>
inline T degreesToRadians (U degrees)
{
return T (degrees * 0.0174532925199433);
}
template <class T, class U>
inline T radiansToDegrees (U radians)
{
T deg = T (radians * U (57.29577951308238));
if (deg < 0)
deg += 360;
return deg;
}
#endif

View File

@@ -0,0 +1,515 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_MATHSFUNCTIONS_H_INCLUDED
#define BEAST_MATHSFUNCTIONS_H_INCLUDED
//==============================================================================
/*
This file sets up some handy mathematical typdefs and functions.
*/
//==============================================================================
// Definitions for the int8, int16, int32, int64 and pointer_sized_int types.
/** A platform-independent 8-bit signed integer type. */
typedef signed char int8;
/** A platform-independent 8-bit unsigned integer type. */
typedef unsigned char uint8;
/** A platform-independent 16-bit signed integer type. */
typedef signed short int16;
/** A platform-independent 16-bit unsigned integer type. */
typedef unsigned short uint16;
/** A platform-independent 32-bit signed integer type. */
typedef signed int int32;
/** A platform-independent 32-bit unsigned integer type. */
typedef unsigned int uint32;
#if BEAST_MSVC
/** A platform-independent 64-bit integer type. */
typedef __int64 int64;
/** A platform-independent 64-bit unsigned integer type. */
typedef unsigned __int64 uint64;
/** A platform-independent macro for writing 64-bit literals, needed because
different compilers have different syntaxes for this.
E.g. writing literal64bit (0x1000000000) will translate to 0x1000000000LL for
GCC, or 0x1000000000 for MSVC.
*/
#define literal64bit(longLiteral) ((__int64) longLiteral)
#else
/** A platform-independent 64-bit integer type. */
typedef long long int64;
/** A platform-independent 64-bit unsigned integer type. */
typedef unsigned long long uint64;
/** A platform-independent macro for writing 64-bit literals, needed because
different compilers have different syntaxes for this.
E.g. writing literal64bit (0x1000000000) will translate to 0x1000000000LL for
GCC, or 0x1000000000 for MSVC.
*/
#define literal64bit(longLiteral) (longLiteral##LL)
#endif
#if BEAST_64BIT
/** A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it. */
typedef int64 pointer_sized_int;
/** An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it. */
typedef uint64 pointer_sized_uint;
#elif BEAST_MSVC
/** A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it. */
typedef _W64 int pointer_sized_int;
/** An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it. */
typedef _W64 unsigned int pointer_sized_uint;
#else
/** A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it. */
typedef int pointer_sized_int;
/** An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it. */
typedef unsigned int pointer_sized_uint;
#endif
#if BEAST_MSVC
typedef pointer_sized_int ssize_t;
#endif
//==============================================================================
// Some indispensible min/max functions
/** Returns the larger of two values. */
template <typename Type>
inline Type bmax (const Type a, const Type b) { return (a < b) ? b : a; }
/** Returns the larger of three values. */
template <typename Type>
inline Type bmax (const Type a, const Type b, const Type c) { return (a < b) ? ((b < c) ? c : b) : ((a < c) ? c : a); }
/** Returns the larger of four values. */
template <typename Type>
inline Type bmax (const Type a, const Type b, const Type c, const Type d) { return bmax (a, bmax (b, c, d)); }
/** Returns the smaller of two values. */
template <typename Type>
inline Type bmin (const Type a, const Type b) { return (b < a) ? b : a; }
/** Returns the smaller of three values. */
template <typename Type>
inline Type bmin (const Type a, const Type b, const Type c) { return (b < a) ? ((c < b) ? c : b) : ((c < a) ? c : a); }
/** Returns the smaller of four values. */
template <typename Type>
inline Type bmin (const Type a, const Type b, const Type c, const Type d) { return bmin (a, bmin (b, c, d)); }
/** Scans an array of values, returning the minimum value that it contains. */
template <typename Type>
const Type findMinimum (const Type* data, int numValues)
{
if (numValues <= 0)
return Type();
Type result (*data++);
while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
{
const Type& v = *data++;
if (v < result) result = v;
}
return result;
}
/** Scans an array of values, returning the maximum value that it contains. */
template <typename Type>
const Type findMaximum (const Type* values, int numValues)
{
if (numValues <= 0)
return Type();
Type result (*values++);
while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
{
const Type& v = *values++;
if (result < v) result = v;
}
return result;
}
/** Scans an array of values, returning the minimum and maximum values that it contains. */
template <typename Type>
void findMinAndMax (const Type* values, int numValues, Type& lowest, Type& highest)
{
if (numValues <= 0)
{
lowest = Type();
highest = Type();
}
else
{
Type mn (*values++);
Type mx (mn);
while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
{
const Type& v = *values++;
if (mx < v) mx = v;
if (v < mn) mn = v;
}
lowest = mn;
highest = mx;
}
}
//==============================================================================
/** Constrains a value to keep it within a given range.
This will check that the specified value lies between the lower and upper bounds
specified, and if not, will return the nearest value that would be in-range. Effectively,
it's like calling bmax (lowerLimit, bmin (upperLimit, value)).
Note that it expects that lowerLimit <= upperLimit. If this isn't true,
the results will be unpredictable.
@param lowerLimit the minimum value to return
@param upperLimit the maximum value to return
@param valueToConstrain the value to try to return
@returns the closest value to valueToConstrain which lies between lowerLimit
and upperLimit (inclusive)
@see blimit0To, bmin, bmax
*/
template <typename Type>
inline Type blimit (const Type lowerLimit,
const Type upperLimit,
const Type valueToConstrain) noexcept
{
bassert (lowerLimit <= upperLimit); // if these are in the wrong order, results are unpredictable..
return (valueToConstrain < lowerLimit) ? lowerLimit
: ((upperLimit < valueToConstrain) ? upperLimit
: valueToConstrain);
}
/** Returns true if a value is at least zero, and also below a specified upper limit.
This is basically a quicker way to write:
@code valueToTest >= 0 && valueToTest < upperLimit
@endcode
*/
template <typename Type>
inline bool isPositiveAndBelow (Type valueToTest, Type upperLimit) noexcept
{
bassert (Type() <= upperLimit); // makes no sense to call this if the upper limit is itself below zero..
return Type() <= valueToTest && valueToTest < upperLimit;
}
template <>
inline bool isPositiveAndBelow (const int valueToTest, const int upperLimit) noexcept
{
bassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero..
return static_cast <unsigned int> (valueToTest) < static_cast <unsigned int> (upperLimit);
}
/** Returns true if a value is at least zero, and also less than or equal to a specified upper limit.
This is basically a quicker way to write:
@code valueToTest >= 0 && valueToTest <= upperLimit
@endcode
*/
template <typename Type>
inline bool isPositiveAndNotGreaterThan (Type valueToTest, Type upperLimit) noexcept
{
bassert (Type() <= upperLimit); // makes no sense to call this if the upper limit is itself below zero..
return Type() <= valueToTest && valueToTest <= upperLimit;
}
template <>
inline bool isPositiveAndNotGreaterThan (const int valueToTest, const int upperLimit) noexcept
{
bassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero..
return static_cast <unsigned int> (valueToTest) <= static_cast <unsigned int> (upperLimit);
}
//==============================================================================
/** Handy function to swap two values. */
template <typename Type>
inline void swapVariables (Type& variable1, Type& variable2)
{
std::swap (variable1, variable2);
}
/** Handy function for getting the number of elements in a simple const C array.
E.g.
@code
static int myArray[] = { 1, 2, 3 };
int numElements = numElementsInArray (myArray) // returns 3
@endcode
*/
template <typename Type, int N>
inline int numElementsInArray (Type (&array)[N])
{
(void) array; // (required to avoid a spurious warning in MS compilers)
(void) sizeof (0[array]); // This line should cause an error if you pass an object with a user-defined subscript operator
return N;
}
//==============================================================================
// Some useful maths functions that aren't always present with all compilers and build settings.
/** Using beast_hypot is easier than dealing with the different types of hypot function
that are provided by the various platforms and compilers. */
template <typename Type>
inline Type beast_hypot (Type a, Type b) noexcept
{
#if BEAST_MSVC
return static_cast <Type> (_hypot (a, b));
#else
return static_cast <Type> (hypot (a, b));
#endif
}
/** 64-bit abs function. */
inline int64 abs64 (const int64 n) noexcept
{
return (n >= 0) ? n : -n;
}
//==============================================================================
/** A predefined value for Pi, at double-precision.
@see float_Pi
*/
const double double_Pi = 3.1415926535897932384626433832795;
/** A predefined value for Pi, at single-precision.
@see double_Pi
*/
const float float_Pi = 3.14159265358979323846f;
//==============================================================================
/** The isfinite() method seems to vary between platforms, so this is a
platform-independent function for it.
*/
template <typename FloatingPointType>
inline bool beast_isfinite (FloatingPointType value)
{
#if BEAST_WINDOWS
return _finite (value);
#elif BEAST_ANDROID
return isfinite (value);
#else
return std::isfinite (value);
#endif
}
//==============================================================================
#if BEAST_MSVC
#pragma optimize ("t", off)
#ifndef __INTEL_COMPILER
#pragma float_control (precise, on, push)
#endif
#endif
/** Fast floating-point-to-integer conversion.
This is faster than using the normal c++ cast to convert a float to an int, and
it will round the value to the nearest integer, rather than rounding it down
like the normal cast does.
Note that this routine gets its speed at the expense of some accuracy, and when
rounding values whose floating point component is exactly 0.5, odd numbers and
even numbers will be rounded up or down differently.
*/
template <typename FloatType>
inline int roundToInt (const FloatType value) noexcept
{
#ifdef __INTEL_COMPILER
#pragma float_control (precise, on, push)
#endif
union { int asInt[2]; double asDouble; } n;
n.asDouble = ((double) value) + 6755399441055744.0;
#if BEAST_BIG_ENDIAN
return n.asInt [1];
#else
return n.asInt [0];
#endif
}
#if BEAST_MSVC
#ifndef __INTEL_COMPILER
#pragma float_control (pop)
#endif
#pragma optimize ("", on) // resets optimisations to the project defaults
#endif
/** Fast floating-point-to-integer conversion.
This is a slightly slower and slightly more accurate version of roundDoubleToInt(). It works
fine for values above zero, but negative numbers are rounded the wrong way.
*/
inline int roundToIntAccurate (const double value) noexcept
{
#ifdef __INTEL_COMPILER
#pragma float_control (pop)
#endif
return roundToInt (value + 1.5e-8);
}
/** Fast floating-point-to-integer conversion.
This is faster than using the normal c++ cast to convert a double to an int, and
it will round the value to the nearest integer, rather than rounding it down
like the normal cast does.
Note that this routine gets its speed at the expense of some accuracy, and when
rounding values whose floating point component is exactly 0.5, odd numbers and
even numbers will be rounded up or down differently. For a more accurate conversion,
see roundDoubleToIntAccurate().
*/
inline int roundDoubleToInt (const double value) noexcept
{
return roundToInt (value);
}
/** Fast floating-point-to-integer conversion.
This is faster than using the normal c++ cast to convert a float to an int, and
it will round the value to the nearest integer, rather than rounding it down
like the normal cast does.
Note that this routine gets its speed at the expense of some accuracy, and when
rounding values whose floating point component is exactly 0.5, odd numbers and
even numbers will be rounded up or down differently.
*/
inline int roundFloatToInt (const float value) noexcept
{
return roundToInt (value);
}
//==============================================================================
/** Returns true if the specified integer is a power-of-two.
*/
template <typename IntegerType>
bool isPowerOfTwo (IntegerType value)
{
return (value & (value - 1)) == 0;
}
/** Returns the smallest power-of-two which is equal to or greater than the given integer.
*/
inline int nextPowerOfTwo (int n) noexcept
{
--n;
n |= (n >> 1);
n |= (n >> 2);
n |= (n >> 4);
n |= (n >> 8);
n |= (n >> 16);
return n + 1;
}
/** Performs a modulo operation, but can cope with the dividend being negative.
The divisor must be greater than zero.
*/
template <typename IntegerType>
IntegerType negativeAwareModulo (IntegerType dividend, const IntegerType divisor) noexcept
{
bassert (divisor > 0);
dividend %= divisor;
return (dividend < 0) ? (dividend + divisor) : dividend;
}
//==============================================================================
#if (BEAST_INTEL && BEAST_32BIT) || defined (DOXYGEN)
/** This macro can be applied to a float variable to check whether it contains a denormalised
value, and to normalise it if necessary.
On CPUs that aren't vulnerable to denormalisation problems, this will have no effect.
*/
#define BEAST_UNDENORMALISE(x) x += 1.0f; x -= 1.0f;
#else
#define BEAST_UNDENORMALISE(x)
#endif
//==============================================================================
/** This namespace contains a few template classes for helping work out class type variations.
*/
namespace TypeHelpers
{
#if BEAST_VC8_OR_EARLIER
#define PARAMETER_TYPE(type) const type&
#else
/** The ParameterType struct is used to find the best type to use when passing some kind
of object as a parameter.
Of course, this is only likely to be useful in certain esoteric template situations.
Because "typename TypeHelpers::ParameterType<SomeClass>::type" is a bit of a mouthful, there's
a PARAMETER_TYPE(SomeClass) macro that you can use to get the same effect.
E.g. "myFunction (PARAMETER_TYPE (int), PARAMETER_TYPE (MyObject))"
would evaluate to "myfunction (int, const MyObject&)", keeping any primitive types as
pass-by-value, but passing objects as a const reference, to avoid copying.
*/
template <typename Type> struct ParameterType { typedef const Type& type; };
#if ! DOXYGEN
template <typename Type> struct ParameterType <Type&> { typedef Type& type; };
template <typename Type> struct ParameterType <Type*> { typedef Type* type; };
template <> struct ParameterType <char> { typedef char type; };
template <> struct ParameterType <unsigned char> { typedef unsigned char type; };
template <> struct ParameterType <short> { typedef short type; };
template <> struct ParameterType <unsigned short> { typedef unsigned short type; };
template <> struct ParameterType <int> { typedef int type; };
template <> struct ParameterType <unsigned int> { typedef unsigned int type; };
template <> struct ParameterType <long> { typedef long type; };
template <> struct ParameterType <unsigned long> { typedef unsigned long type; };
template <> struct ParameterType <int64> { typedef int64 type; };
template <> struct ParameterType <uint64> { typedef uint64 type; };
template <> struct ParameterType <bool> { typedef bool type; };
template <> struct ParameterType <float> { typedef float type; };
template <> struct ParameterType <double> { typedef double type; };
#endif
/** A helpful macro to simplify the use of the ParameterType template.
@see ParameterType
*/
#define PARAMETER_TYPE(a) typename TypeHelpers::ParameterType<a>::type
#endif
/** These templates are designed to take a type, and if it's a double, they return a double
type; for anything else, they return a float type.
*/
template <typename Type> struct SmallestFloatType { typedef float type; };
template <> struct SmallestFloatType <double> { typedef double type; };
}
//==============================================================================
#endif // BEAST_MATHSFUNCTIONS_H_INCLUDED

View File

@@ -0,0 +1,487 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
// http://code.google.com/p/smhasher/
namespace Murmur
{
//-----------------------------------------------------------------------------
// Platform-specific functions and macros
// Microsoft Visual Studio
#if BEAST_MSVC
#define ROTL32(x,y) _rotl(x,y)
#define ROTL64(x,y) _rotl64(x,y)
#define BIG_CONSTANT(x) (x)
// Other compilers
#else
static inline uint32_t rotl32 ( uint32_t x, int8_t r )
{
return (x << r) | (x >> (32 - r));
}
static inline uint64_t rotl64 ( uint64_t x, int8_t r )
{
return (x << r) | (x >> (64 - r));
}
#define ROTL32(x,y) rotl32(x,y)
#define ROTL64(x,y) rotl64(x,y)
#define BIG_CONSTANT(x) (x##LLU)
#endif
//-----------------------------------------------------------------------------
// Block read - if your platform needs to do endian-swapping or can only
// handle aligned reads, do the conversion here
static forcedinline uint32_t getblock ( const uint32_t* p, int i )
{
return p[i];
}
static forcedinline uint64_t getblock ( const uint64_t* p, int i )
{
return p[i];
}
//-----------------------------------------------------------------------------
// Finalization mix - force all bits of a hash block to avalanche
static forcedinline uint32_t fmix ( uint32_t h )
{
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
//----------
static forcedinline uint64_t fmix ( uint64_t k )
{
k ^= k >> 33;
k *= BIG_CONSTANT (0xff51afd7ed558ccd);
k ^= k >> 33;
k *= BIG_CONSTANT (0xc4ceb9fe1a85ec53);
k ^= k >> 33;
return k;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x86_32 ( const void* key, int len,
uint32_t seed, void* out )
{
const uint8_t* data = (const uint8_t*)key;
const int nblocks = len / 4;
uint32_t h1 = seed;
uint32_t c1 = 0xcc9e2d51;
uint32_t c2 = 0x1b873593;
//----------
// body
const uint32_t* blocks = (const uint32_t*) (data + nblocks * 4);
for (int i = -nblocks; i; i++)
{
uint32_t k1 = getblock (blocks, i);
k1 *= c1;
k1 = ROTL32 (k1, 15);
k1 *= c2;
h1 ^= k1;
h1 = ROTL32 (h1, 13);
h1 = h1 * 5 + 0xe6546b64;
}
//----------
// tail
const uint8_t* tail = (const uint8_t*) (data + nblocks * 4);
uint32_t k1 = 0;
switch (len & 3)
{
case 3:
k1 ^= tail[2] << 16;
case 2:
k1 ^= tail[1] << 8;
case 1:
k1 ^= tail[0];
k1 *= c1;
k1 = ROTL32 (k1, 15);
k1 *= c2;
h1 ^= k1;
};
//----------
// finalization
h1 ^= len;
h1 = fmix (h1);
* (uint32_t*)out = h1;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x86_128 ( const void* key, const int len,
uint32_t seed, void* out )
{
const uint8_t* data = (const uint8_t*)key;
const int nblocks = len / 16;
uint32_t h1 = seed;
uint32_t h2 = seed;
uint32_t h3 = seed;
uint32_t h4 = seed;
uint32_t c1 = 0x239b961b;
uint32_t c2 = 0xab0e9789;
uint32_t c3 = 0x38b34ae5;
uint32_t c4 = 0xa1e38b93;
//----------
// body
const uint32_t* blocks = (const uint32_t*) (data + nblocks * 16);
for (int i = -nblocks; i; i++)
{
uint32_t k1 = getblock (blocks, i * 4 + 0);
uint32_t k2 = getblock (blocks, i * 4 + 1);
uint32_t k3 = getblock (blocks, i * 4 + 2);
uint32_t k4 = getblock (blocks, i * 4 + 3);
k1 *= c1;
k1 = ROTL32 (k1, 15);
k1 *= c2;
h1 ^= k1;
h1 = ROTL32 (h1, 19);
h1 += h2;
h1 = h1 * 5 + 0x561ccd1b;
k2 *= c2;
k2 = ROTL32 (k2, 16);
k2 *= c3;
h2 ^= k2;
h2 = ROTL32 (h2, 17);
h2 += h3;
h2 = h2 * 5 + 0x0bcaa747;
k3 *= c3;
k3 = ROTL32 (k3, 17);
k3 *= c4;
h3 ^= k3;
h3 = ROTL32 (h3, 15);
h3 += h4;
h3 = h3 * 5 + 0x96cd1c35;
k4 *= c4;
k4 = ROTL32 (k4, 18);
k4 *= c1;
h4 ^= k4;
h4 = ROTL32 (h4, 13);
h4 += h1;
h4 = h4 * 5 + 0x32ac3b17;
}
//----------
// tail
const uint8_t* tail = (const uint8_t*) (data + nblocks * 16);
uint32_t k1 = 0;
uint32_t k2 = 0;
uint32_t k3 = 0;
uint32_t k4 = 0;
switch (len & 15)
{
case 15:
k4 ^= tail[14] << 16;
case 14:
k4 ^= tail[13] << 8;
case 13:
k4 ^= tail[12] << 0;
k4 *= c4;
k4 = ROTL32 (k4, 18);
k4 *= c1;
h4 ^= k4;
case 12:
k3 ^= tail[11] << 24;
case 11:
k3 ^= tail[10] << 16;
case 10:
k3 ^= tail[ 9] << 8;
case 9:
k3 ^= tail[ 8] << 0;
k3 *= c3;
k3 = ROTL32 (k3, 17);
k3 *= c4;
h3 ^= k3;
case 8:
k2 ^= tail[ 7] << 24;
case 7:
k2 ^= tail[ 6] << 16;
case 6:
k2 ^= tail[ 5] << 8;
case 5:
k2 ^= tail[ 4] << 0;
k2 *= c2;
k2 = ROTL32 (k2, 16);
k2 *= c3;
h2 ^= k2;
case 4:
k1 ^= tail[ 3] << 24;
case 3:
k1 ^= tail[ 2] << 16;
case 2:
k1 ^= tail[ 1] << 8;
case 1:
k1 ^= tail[ 0] << 0;
k1 *= c1;
k1 = ROTL32 (k1, 15);
k1 *= c2;
h1 ^= k1;
};
//----------
// finalization
h1 ^= len;
h2 ^= len;
h3 ^= len;
h4 ^= len;
h1 += h2;
h1 += h3;
h1 += h4;
h2 += h1;
h3 += h1;
h4 += h1;
h1 = fmix (h1);
h2 = fmix (h2);
h3 = fmix (h3);
h4 = fmix (h4);
h1 += h2;
h1 += h3;
h1 += h4;
h2 += h1;
h3 += h1;
h4 += h1;
((uint32_t*)out)[0] = h1;
((uint32_t*)out)[1] = h2;
((uint32_t*)out)[2] = h3;
((uint32_t*)out)[3] = h4;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x64_128 ( const void* key, const int len,
const uint32_t seed, void* out )
{
const uint8_t* data = (const uint8_t*)key;
const int nblocks = len / 16;
uint64_t h1 = seed;
uint64_t h2 = seed;
uint64_t c1 = BIG_CONSTANT (0x87c37b91114253d5);
uint64_t c2 = BIG_CONSTANT (0x4cf5ad432745937f);
//----------
// body
const uint64_t* blocks = (const uint64_t*) (data);
for (int i = 0; i < nblocks; i++)
{
uint64_t k1 = getblock (blocks, i * 2 + 0);
uint64_t k2 = getblock (blocks, i * 2 + 1);
k1 *= c1;
k1 = ROTL64 (k1, 31);
k1 *= c2;
h1 ^= k1;
h1 = ROTL64 (h1, 27);
h1 += h2;
h1 = h1 * 5 + 0x52dce729;
k2 *= c2;
k2 = ROTL64 (k2, 33);
k2 *= c1;
h2 ^= k2;
h2 = ROTL64 (h2, 31);
h2 += h1;
h2 = h2 * 5 + 0x38495ab5;
}
//----------
// tail
const uint8_t* tail = (const uint8_t*) (data + nblocks * 16);
uint64_t k1 = 0;
uint64_t k2 = 0;
switch (len & 15)
{
case 15:
k2 ^= uint64_t (tail[14]) << 48;
case 14:
k2 ^= uint64_t (tail[13]) << 40;
case 13:
k2 ^= uint64_t (tail[12]) << 32;
case 12:
k2 ^= uint64_t (tail[11]) << 24;
case 11:
k2 ^= uint64_t (tail[10]) << 16;
case 10:
k2 ^= uint64_t (tail[ 9]) << 8;
case 9:
k2 ^= uint64_t (tail[ 8]) << 0;
k2 *= c2;
k2 = ROTL64 (k2, 33);
k2 *= c1;
h2 ^= k2;
case 8:
k1 ^= uint64_t (tail[ 7]) << 56;
case 7:
k1 ^= uint64_t (tail[ 6]) << 48;
case 6:
k1 ^= uint64_t (tail[ 5]) << 40;
case 5:
k1 ^= uint64_t (tail[ 4]) << 32;
case 4:
k1 ^= uint64_t (tail[ 3]) << 24;
case 3:
k1 ^= uint64_t (tail[ 2]) << 16;
case 2:
k1 ^= uint64_t (tail[ 1]) << 8;
case 1:
k1 ^= uint64_t (tail[ 0]) << 0;
k1 *= c1;
k1 = ROTL64 (k1, 31);
k1 *= c2;
h1 ^= k1;
};
//----------
// finalization
h1 ^= len;
h2 ^= len;
h1 += h2;
h2 += h1;
h1 = fmix (h1);
h2 = fmix (h2);
h1 += h2;
h2 += h1;
((uint64_t*)out)[0] = h1;
((uint64_t*)out)[1] = h2;
}
}

View File

@@ -0,0 +1,66 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_MURMURHASH_H_INCLUDED
#define BEAST_MURMURHASH_H_INCLUDED
// Original source code links in .cpp file
// This file depends on some Beast declarations and defines
namespace Murmur
{
extern void MurmurHash3_x86_32 (const void* key, int len, uint32 seed, void* out);
extern void MurmurHash3_x86_128 (const void* key, int len, uint32 seed, void* out);
extern void MurmurHash3_x64_128 (const void* key, int len, uint32 seed, void* out);
// Uses Beast to choose an appropriate routine
// This handy template deduces which size hash is desired
template <typename HashType>
inline void Hash (const void* key, int len, uint32 seed, HashType* out)
{
switch (8 * sizeof (HashType))
{
case 32:
MurmurHash3_x86_32 (key, len, seed, out);
break;
#if BEAST_64BIT
case 128:
MurmurHash3_x64_128 (key, len, seed, out);
break;
#else
case 128:
MurmurHash3_x86_128 (key, len, seed, out);
break;
#endif
default:
Throw (std::runtime_error ("invalid key size in MurmurHash"));
break;
};
}
}
#endif

View File

@@ -0,0 +1,187 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
Random::Random (const int64 seedValue) noexcept
: seed (seedValue)
{
nextInt (); // fixes a bug where the first int is always 0
}
Random::Random()
: seed (1)
{
setSeedRandomly();
}
Random::~Random() noexcept
{
}
void Random::setSeed (const int64 newSeed) noexcept
{
seed = newSeed;
nextInt (); // fixes a bug where the first int is always 0
}
void Random::combineSeed (const int64 seedValue) noexcept
{
seed ^= nextInt64() ^ seedValue;
}
void Random::setSeedRandomly()
{
static int64 globalSeed = 0;
combineSeed (globalSeed ^ (int64) (pointer_sized_int) this);
combineSeed (Time::getMillisecondCounter());
combineSeed (Time::getHighResolutionTicks());
combineSeed (Time::getHighResolutionTicksPerSecond());
combineSeed (Time::currentTimeMillis());
globalSeed ^= seed;
nextInt (); // fixes a bug where the first int is always 0
}
Random& Random::getSystemRandom() noexcept
{
static Random sysRand;
return sysRand;
}
//==============================================================================
int Random::nextInt() noexcept
{
seed = (seed * literal64bit (0x5deece66d) + 11) & literal64bit (0xffffffffffff);
return (int) (seed >> 16);
}
int Random::nextInt (const int maxValue) noexcept
{
bassert (maxValue > 0);
return (int) ((((unsigned int) nextInt()) * (uint64) maxValue) >> 32);
}
int64 Random::nextInt64() noexcept
{
return (((int64) nextInt()) << 32) | (int64) (uint64) (uint32) nextInt();
}
bool Random::nextBool() noexcept
{
return (nextInt() & 0x40000000) != 0;
}
float Random::nextFloat() noexcept
{
return static_cast <uint32> (nextInt()) / (float) 0xffffffff;
}
double Random::nextDouble() noexcept
{
return static_cast <uint32> (nextInt()) / (double) 0xffffffff;
}
BigInteger Random::nextLargeNumber (const BigInteger& maximumValue)
{
BigInteger n;
do
{
fillBitsRandomly (n, 0, maximumValue.getHighestBit() + 1);
}
while (n >= maximumValue);
return n;
}
void Random::fillBitsRandomly (void* const buffer, size_t bytes)
{
int* d = static_cast<int*> (buffer);
for (; bytes >= sizeof (int); bytes -= sizeof (int))
*d++ = nextInt();
if (bytes > 0)
{
const int lastBytes = nextInt();
memcpy (d, &lastBytes, bytes);
}
}
void Random::fillBitsRandomly (BigInteger& arrayToChange, int startBit, int numBits)
{
arrayToChange.setBit (startBit + numBits - 1, true); // to force the array to pre-allocate space
while ((startBit & 31) != 0 && numBits > 0)
{
arrayToChange.setBit (startBit++, nextBool());
--numBits;
}
while (numBits >= 32)
{
arrayToChange.setBitRangeAsInt (startBit, 32, (unsigned int) nextInt());
startBit += 32;
numBits -= 32;
}
while (--numBits >= 0)
arrayToChange.setBit (startBit + numBits, nextBool());
}
//==============================================================================
class RandomTests : public UnitTest
{
public:
RandomTests() : UnitTest ("Random", "beast") {}
void runTest()
{
beginTestCase ("Random");
for (int j = 10; --j >= 0;)
{
Random r;
r.setSeedRandomly();
for (int i = 20; --i >= 0;)
{
expect (r.nextDouble() >= 0.0 && r.nextDouble() < 1.0);
expect (r.nextFloat() >= 0.0f && r.nextFloat() < 1.0f);
expect (r.nextInt (5) >= 0 && r.nextInt (5) < 5);
expect (r.nextInt (1) == 0);
int n = r.nextInt (50) + 1;
expect (r.nextInt (n) >= 0 && r.nextInt (n) < n);
n = r.nextInt (0x7ffffffe) + 1;
expect (r.nextInt (n) >= 0 && r.nextInt (n) < n);
}
}
}
};
static RandomTests randomTests;

View File

@@ -0,0 +1,133 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_RANDOM_H_INCLUDED
#define BEAST_RANDOM_H_INCLUDED
//==============================================================================
/**
A random number generator.
You can create a Random object and use it to generate a sequence of random numbers.
*/
class BEAST_API Random : LeakChecked <Random>
{
public:
//==============================================================================
/** Creates a Random object based on a seed value.
For a given seed value, the subsequent numbers generated by this object
will be predictable, so a good idea is to set this value based
on the time, e.g.
new Random (Time::currentTimeMillis())
*/
explicit Random (int64 seedValue) noexcept;
/** Creates a Random object using a random seed value.
Internally, this calls setSeedRandomly() to randomise the seed.
*/
Random();
/** Destructor. */
~Random() noexcept;
/** Returns the next random 32 bit integer.
@returns a random integer from the full range 0x80000000 to 0x7fffffff
*/
int nextInt() noexcept;
/** Returns the next random number, limited to a given range.
The maxValue parameter may not be negative, or zero.
@returns a random integer between 0 (inclusive) and maxValue (exclusive).
*/
int nextInt (int maxValue) noexcept;
/** Returns the next 64-bit random number.
@returns a random integer from the full range 0x8000000000000000 to 0x7fffffffffffffff
*/
int64 nextInt64() noexcept;
/** Returns the next random floating-point number.
@returns a random value in the range 0 to 1.0
*/
float nextFloat() noexcept;
/** Returns the next random floating-point number.
@returns a random value in the range 0 to 1.0
*/
double nextDouble() noexcept;
/** Returns the next random boolean value.
*/
bool nextBool() noexcept;
/** Returns a BigInteger containing a random number.
@returns a random value in the range 0 to (maximumValue - 1).
*/
BigInteger nextLargeNumber (const BigInteger& maximumValue);
/** Fills a block of memory with random values. */
void fillBitsRandomly (void* bufferToFill, size_t sizeInBytes);
/** Sets a range of bits in a BigInteger to random values. */
void fillBitsRandomly (BigInteger& arrayToChange, int startBit, int numBits);
//==============================================================================
/** Resets this Random object to a given seed value. */
void setSeed (int64 newSeed) noexcept;
/** Merges this object's seed with another value.
This sets the seed to be a value created by combining the current seed and this
new value.
*/
void combineSeed (int64 seedValue) noexcept;
/** Reseeds this generator using a value generated from various semi-random system
properties like the current time, etc.
Because this function convolves the time with the last seed value, calling
it repeatedly will increase the randomness of the final result.
*/
void setSeedRandomly();
/** The overhead of creating a new Random object is fairly small, but if you want to avoid
it, you can call this method to get a global shared Random object.
It's not thread-safe though, so threads should use their own Random object, otherwise
you run the risk of your random numbers becoming.. erm.. randomly corrupted..
*/
static Random& getSystemRandom() noexcept;
private:
//==============================================================================
int64 seed;
};
#endif // BEAST_RANDOM_H_INCLUDED

View File

@@ -0,0 +1,259 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_RANGE_H_INCLUDED
#define BEAST_RANGE_H_INCLUDED
//==============================================================================
/** A general-purpose range object, that simply represents any linear range with
a start and end point.
The templated parameter is expected to be a primitive integer or floating point
type, though class types could also be used if they behave in a number-like way.
*/
template <typename ValueType>
class Range
{
public:
//==============================================================================
/** Constructs an empty range. */
Range() noexcept : start(), end()
{
}
/** Constructs a range with given start and end values. */
Range (const ValueType startValue, const ValueType endValue) noexcept
: start (startValue), end (bmax (startValue, endValue))
{
}
/** Constructs a copy of another range. */
Range (const Range& other) noexcept
: start (other.start), end (other.end)
{
}
/** Copies another range object. */
Range& operator= (Range other) noexcept
{
start = other.start;
end = other.end;
return *this;
}
/** Returns the range that lies between two positions (in either order). */
static Range between (const ValueType position1, const ValueType position2) noexcept
{
return position1 < position2 ? Range (position1, position2)
: Range (position2, position1);
}
/** Returns a range with the specified start position and a length of zero. */
static Range emptyRange (const ValueType start) noexcept
{
return Range (start, start);
}
//==============================================================================
/** Returns the start of the range. */
inline ValueType getStart() const noexcept { return start; }
/** Returns the length of the range. */
inline ValueType getLength() const noexcept { return end - start; }
/** Returns the end of the range. */
inline ValueType getEnd() const noexcept { return end; }
/** Returns true if the range has a length of zero. */
inline bool isEmpty() const noexcept { return start == end; }
//==============================================================================
/** Changes the start position of the range, leaving the end position unchanged.
If the new start position is higher than the current end of the range, the end point
will be pushed along to equal it, leaving an empty range at the new position.
*/
void setStart (const ValueType newStart) noexcept
{
start = newStart;
if (end < newStart)
end = newStart;
}
/** Returns a range with the same end as this one, but a different start.
If the new start position is higher than the current end of the range, the end point
will be pushed along to equal it, returning an empty range at the new position.
*/
Range withStart (const ValueType newStart) const noexcept
{
return Range (newStart, bmax (newStart, end));
}
/** Returns a range with the same length as this one, but moved to have the given start position. */
Range movedToStartAt (const ValueType newStart) const noexcept
{
return Range (newStart, end + (newStart - start));
}
/** Changes the end position of the range, leaving the start unchanged.
If the new end position is below the current start of the range, the start point
will be pushed back to equal the new end point.
*/
void setEnd (const ValueType newEnd) noexcept
{
end = newEnd;
if (newEnd < start)
start = newEnd;
}
/** Returns a range with the same start position as this one, but a different end.
If the new end position is below the current start of the range, the start point
will be pushed back to equal the new end point.
*/
Range withEnd (const ValueType newEnd) const noexcept
{
return Range (bmin (start, newEnd), newEnd);
}
/** Returns a range with the same length as this one, but moved to have the given end position. */
Range movedToEndAt (const ValueType newEnd) const noexcept
{
return Range (start + (newEnd - end), newEnd);
}
/** Changes the length of the range.
Lengths less than zero are treated as zero.
*/
void setLength (const ValueType newLength) noexcept
{
end = start + bmax (ValueType(), newLength);
}
/** Returns a range with the same start as this one, but a different length.
Lengths less than zero are treated as zero.
*/
Range withLength (const ValueType newLength) const noexcept
{
return Range (start, start + newLength);
}
//==============================================================================
/** Adds an amount to the start and end of the range. */
inline Range operator+= (const ValueType amountToAdd) noexcept
{
start += amountToAdd;
end += amountToAdd;
return *this;
}
/** Subtracts an amount from the start and end of the range. */
inline Range operator-= (const ValueType amountToSubtract) noexcept
{
start -= amountToSubtract;
end -= amountToSubtract;
return *this;
}
/** Returns a range that is equal to this one with an amount added to its
start and end.
*/
Range operator+ (const ValueType amountToAdd) const noexcept
{
return Range (start + amountToAdd, end + amountToAdd);
}
/** Returns a range that is equal to this one with the specified amount
subtracted from its start and end. */
Range operator- (const ValueType amountToSubtract) const noexcept
{
return Range (start - amountToSubtract, end - amountToSubtract);
}
bool operator== (Range other) const noexcept { return start == other.start && end == other.end; }
bool operator!= (Range other) const noexcept { return start != other.start || end != other.end; }
//==============================================================================
/** Returns true if the given position lies inside this range. */
bool contains (const ValueType position) const noexcept
{
return start <= position && position < end;
}
/** Returns the nearest value to the one supplied, which lies within the range. */
ValueType clipValue (const ValueType value) const noexcept
{
return blimit (start, end, value);
}
/** Returns true if the given range lies entirely inside this range. */
bool contains (Range other) const noexcept
{
return start <= other.start && end >= other.end;
}
/** Returns true if the given range intersects this one. */
bool intersects (Range other) const noexcept
{
return other.start < end && start < other.end;
}
/** Returns the range that is the intersection of the two ranges, or an empty range
with an undefined start position if they don't overlap. */
Range getIntersectionWith (Range other) const noexcept
{
return Range (bmax (start, other.start),
bmin (end, other.end));
}
/** Returns the smallest range that contains both this one and the other one. */
Range getUnionWith (Range other) const noexcept
{
return Range (bmin (start, other.start),
bmax (end, other.end));
}
/** Returns a given range, after moving it forwards or backwards to fit it
within this range.
If the supplied range has a greater length than this one, the return value
will be this range.
Otherwise, if the supplied range is smaller than this one, the return value
will be the new range, shifted forwards or backwards so that it doesn't extend
beyond this one, but keeping its original length.
*/
Range constrainRange (Range rangeToConstrain) const noexcept
{
const ValueType otherLen = rangeToConstrain.getLength();
return getLength() <= otherLen
? *this
: rangeToConstrain.movedToStartAt (blimit (start, end - otherLen, rangeToConstrain.getStart()));
}
private:
//==============================================================================
ValueType start, end;
};
#endif // BEAST_RANGE_H_INCLUDED

View File

@@ -0,0 +1,144 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_UINT24_H_INCLUDED
#define BEAST_UINT24_H_INCLUDED
/** A 24 bit unsigned integer.
We try to be as compatible as possible with built in types.
*/
class uint24 : public SafeBool <uint24>
{
public:
enum { mask = 0xffffff };
inline uint24 () noexcept { /* uninitialized */ }
inline uint24 (uint24 const& other) noexcept : m_value (other.m_value) { }
inline uint24& operator= (uint24 const& other) noexcept { m_value = other.m_value; return *this; }
template <typename IntegralType> inline uint24 (IntegralType value) noexcept : m_value (value & mask) { }
template <typename IntegralType> inline uint24& operator= (IntegralType value) noexcept { m_value = value & mask; return *this; }
inline uint32 get () const noexcept { return m_value; }
inline bool asBoolean () const noexcept { return m_value != 0; }
inline operator String () const { return String (m_value); }
inline uint24& operator++ () noexcept { (++m_value) &= mask; return *this; }
inline uint24& operator-- () noexcept { (--m_value) &= mask; return *this; }
inline uint24 operator++ (int) noexcept { return uint24 (m_value + 1); }
inline uint24 operator-- (int) noexcept { return uint24 (m_value - 1); }
inline uint24& operator~ () { m_value = (~ m_value) & mask; return *this; }
inline uint24& operator+= (uint24 const& rhs) { m_value = (m_value + rhs.m_value) & mask; return *this; }
inline uint24& operator-= (uint24 const& rhs) { m_value = (m_value - rhs.m_value) & mask; return *this; }
inline uint24& operator*= (uint24 const& rhs) { m_value = (m_value * rhs.m_value) & mask; return *this; }
inline uint24& operator/= (uint24 const& rhs) { m_value = (m_value / rhs.m_value) & mask; return *this; }
inline uint24& operator|= (uint24 const& rhs) { m_value = (m_value | rhs.m_value) & mask; return *this; }
inline uint24& operator&= (uint24 const& rhs) { m_value = (m_value & rhs.m_value) & mask; return *this; }
inline uint24& operator^= (uint24 const& rhs) { m_value = (m_value ^ rhs.m_value) & mask; return *this; }
template <typename IntegralType> inline uint24& operator+= (IntegralType value) { m_value = (m_value + value) & mask; return *this; }
template <typename IntegralType> inline uint24& operator-= (IntegralType value) { m_value = (m_value - value) & mask; return *this; }
template <typename IntegralType> inline uint24& operator*= (IntegralType value) { m_value = (m_value * value) & mask; return *this; }
template <typename IntegralType> inline uint24& operator/= (IntegralType value) { m_value = (m_value / value) & mask; return *this; }
template <typename IntegralType> inline uint24& operator|= (IntegralType value) { m_value = (m_value | value) & mask; return *this; }
template <typename IntegralType> inline uint24& operator&= (IntegralType value) { m_value = (m_value & value) & mask; return *this; }
template <typename IntegralType> inline uint24& operator^= (IntegralType value) { m_value = (m_value ^ value) & mask; return *this; }
template <typename IntegralType> inline bool operator== (IntegralType value) const noexcept { return m_value == value; }
template <typename IntegralType> inline bool operator!= (IntegralType value) const noexcept { return m_value != value; }
template <typename IntegralType> inline bool operator< (IntegralType value) const noexcept { return m_value < value; }
template <typename IntegralType> inline bool operator> (IntegralType value) const noexcept { return m_value > value; }
template <typename IntegralType> inline bool operator<= (IntegralType value) const noexcept { return m_value <= value; }
template <typename IntegralType> inline bool operator>= (IntegralType value) const noexcept { return m_value >= value; }
// Construct from raw bytes
static uint24 from3RawBytes (void const* buf)
{
uint24 result;
uint8* const raw (reinterpret_cast <uint8*> (&result.m_value));
uint8 const* const data (reinterpret_cast <uint8 const*> (buf));
#if BEAST_LITTLE_ENDIAN
raw [0] = data [0];
raw [1] = data [1];
raw [2] = data [2];
raw [3] = 0;
#else
raw [0] = 0;
raw [1] = data [0];
raw [2] = data [1];
raw [3] = data [2];
#endif
return result;
}
private:
uint24* operator&();
uint24 const* operator&() const;
friend struct detail::SwapBytes <uint24>;
inline uint8& operator[] (int index) noexcept { bassert (index >= 0 && index < 3); return raw () [index]; }
inline uint8 operator[] (int index) const noexcept { bassert (index >= 0 && index < 3); return raw () [index]; }
#if BEAST_LITTLE_ENDIAN
inline uint8* raw () noexcept { return reinterpret_cast <uint8*> (&m_value); }
inline uint8 const* raw () const noexcept { return reinterpret_cast <uint8 const*> (&m_value); }
#else
inline uint8* raw () noexcept { return reinterpret_cast <uint8*> (&m_value) + 1; }
inline uint8 const* raw () const noexcept { return reinterpret_cast <uint8 const*> (&m_value) + 1; }
#endif
uint32 m_value;
};
inline uint24 const operator~ (uint24 const& value) noexcept { return uint24 (~value.get ()); }
inline uint24 const operator+ (uint24 const& lhs, uint24 const& rhs) noexcept { return uint24 (lhs.get () + rhs.get ()); }
inline uint24 const operator- (uint24 const& lhs, uint24 const& rhs) noexcept { return uint24 (lhs.get () - rhs.get ()); }
inline uint24 const operator/ (uint24 const& lhs, uint24 const& rhs) noexcept { return uint24 (lhs.get () / rhs.get ()); }
inline uint24 const operator* (uint24 const& lhs, uint24 const& rhs) noexcept { return uint24 (lhs.get () * rhs.get ()); }
inline uint24 const operator| (uint24 const& lhs, uint24 const& rhs) noexcept { return uint24 (lhs.get () ^ rhs.get ()); }
inline uint24 const operator& (uint24 const& lhs, uint24 const& rhs) noexcept { return uint24 (lhs.get () & rhs.get ()); }
inline uint24 const operator^ (uint24 const& lhs, uint24 const& rhs) noexcept { return uint24 (lhs.get () ^ rhs.get ()); }
inline bool operator== (uint24 const& lhs, uint24 const& rhs) noexcept { return lhs.get () == rhs.get (); }
inline bool operator!= (uint24 const& lhs, uint24 const& rhs) noexcept { return lhs.get () != rhs.get (); }
inline bool operator< (uint24 const& lhs, uint24 const& rhs) noexcept { return lhs.get () < rhs.get (); }
inline bool operator> (uint24 const& lhs, uint24 const& rhs) noexcept { return lhs.get () > rhs.get (); }
inline bool operator<= (uint24 const& lhs, uint24 const& rhs) noexcept { return lhs.get () <= rhs.get (); }
inline bool operator>= (uint24 const& lhs, uint24 const& rhs) noexcept { return lhs.get () >= rhs.get (); }
/** SwapBytes specialization uint24. */
namespace detail
{
template <>
struct SwapBytes <uint24>
{
inline uint24 const operator() (uint24 const& value) const noexcept
{
#if BEAST_LITTLE_ENDIAN
uint24 result;
result [0] = value [2];
result [1] = value [1];
result [2] = value [0];
result [3] = 0;
return result;
#else
return value;
#endif
}
};
}
#endif