migrating to the latest JUCE version

This commit is contained in:
2022-11-04 23:11:33 +01:00
committed by Nikolai Rodionov
parent 4257a0f8ba
commit faf8f18333
2796 changed files with 888518 additions and 784244 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,342 +1,342 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. 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.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
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.
@tags{Core}
*/
class JUCE_API 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&);
/** Move constructor */
BigInteger (BigInteger&&) noexcept;
/** Move assignment operator */
BigInteger& operator= (BigInteger&&) noexcept;
/** Destructor. */
~BigInteger();
//==============================================================================
/** Copies another BigInteger onto this one. */
BigInteger& operator= (const BigInteger&);
/** Swaps the internal contents of this with another object. */
void swapWith (BigInteger&) 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 32 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;
/** Attempts to get the lowest 64 bits of the value as an integer.
If the value is bigger than the integer limits, this will return only the lower bits.
*/
int64 toInt64() const noexcept;
//==============================================================================
/** Resets the value to 0. */
void clear() noexcept;
/** 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;
//==============================================================================
/** 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;
//==============================================================================
// All the standard arithmetic ops...
BigInteger& operator+= (const BigInteger&);
BigInteger& operator-= (const BigInteger&);
BigInteger& operator*= (const BigInteger&);
BigInteger& operator/= (const BigInteger&);
BigInteger& operator|= (const BigInteger&);
BigInteger& operator&= (const BigInteger&);
BigInteger& operator^= (const BigInteger&);
BigInteger& operator%= (const BigInteger&);
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&) const;
BigInteger operator- (const BigInteger&) const;
BigInteger operator* (const BigInteger&) const;
BigInteger operator/ (const BigInteger&) const;
BigInteger operator| (const BigInteger&) const;
BigInteger operator& (const BigInteger&) const;
BigInteger operator^ (const BigInteger&) const;
BigInteger operator% (const BigInteger&) const;
BigInteger operator<< (int numBitsToShift) const;
BigInteger operator>> (int numBitsToShift) const;
bool operator== (const BigInteger&) const noexcept;
bool operator!= (const BigInteger&) const noexcept;
bool operator< (const BigInteger&) const noexcept;
bool operator<= (const BigInteger&) const noexcept;
bool operator> (const BigInteger&) const noexcept;
bool operator>= (const BigInteger&) 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 argument. */
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);
/** Performs the Montgomery Multiplication with modulo.
This object is left containing the result value: ((this * other) * R1) % modulus.
To get this result, we need modulus, modulusp and k such as R = 2^k, with
modulus * modulusp - R * R1 = GCD(modulus, R) = 1
*/
void montgomeryMultiplication (const BigInteger& other, const BigInteger& modulus,
const BigInteger& modulusp, int k);
/** Performs the Extended Euclidean algorithm.
This method will set the xOut and yOut arguments such that (a * xOut) - (b * yOut) = GCD (a, b).
On return, this object is left containing the value of the GCD.
*/
void extendedEuclidean (const BigInteger& a, const BigInteger& b,
BigInteger& xOut, BigInteger& yOut);
//==============================================================================
/** 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 (StringRef 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:
//==============================================================================
enum { numPreallocatedInts = 4 };
HeapBlock<uint32> heapAllocation;
uint32 preallocated[numPreallocatedInts];
size_t allocatedSize;
int highestBit = -1;
bool negative = false;
uint32* getValues() const noexcept;
uint32* ensureSize (size_t);
void shiftLeft (int bits, int startBit);
void shiftRight (int bits, int startBit);
JUCE_LEAK_DETECTOR (BigInteger)
};
/** Writes a BigInteger to an OutputStream as a UTF8 decimal string. */
OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const BigInteger& value);
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. 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.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
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.
@tags{Core}
*/
class JUCE_API 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&);
/** Move constructor */
BigInteger (BigInteger&&) noexcept;
/** Move assignment operator */
BigInteger& operator= (BigInteger&&) noexcept;
/** Destructor. */
~BigInteger() = default;
//==============================================================================
/** Copies another BigInteger onto this one. */
BigInteger& operator= (const BigInteger&);
/** Swaps the internal contents of this with another object. */
void swapWith (BigInteger&) 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 32 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;
/** Attempts to get the lowest 64 bits of the value as an integer.
If the value is bigger than the integer limits, this will return only the lower bits.
*/
int64 toInt64() const noexcept;
//==============================================================================
/** Resets the value to 0. */
void clear() noexcept;
/** 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;
//==============================================================================
/** 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;
//==============================================================================
// All the standard arithmetic ops...
BigInteger& operator+= (const BigInteger&);
BigInteger& operator-= (const BigInteger&);
BigInteger& operator*= (const BigInteger&);
BigInteger& operator/= (const BigInteger&);
BigInteger& operator|= (const BigInteger&);
BigInteger& operator&= (const BigInteger&);
BigInteger& operator^= (const BigInteger&);
BigInteger& operator%= (const BigInteger&);
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&) const;
BigInteger operator- (const BigInteger&) const;
BigInteger operator* (const BigInteger&) const;
BigInteger operator/ (const BigInteger&) const;
BigInteger operator| (const BigInteger&) const;
BigInteger operator& (const BigInteger&) const;
BigInteger operator^ (const BigInteger&) const;
BigInteger operator% (const BigInteger&) const;
BigInteger operator<< (int numBitsToShift) const;
BigInteger operator>> (int numBitsToShift) const;
bool operator== (const BigInteger&) const noexcept;
bool operator!= (const BigInteger&) const noexcept;
bool operator< (const BigInteger&) const noexcept;
bool operator<= (const BigInteger&) const noexcept;
bool operator> (const BigInteger&) const noexcept;
bool operator>= (const BigInteger&) 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 argument. */
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);
/** Performs the Montgomery Multiplication with modulo.
This object is left containing the result value: ((this * other) * R1) % modulus.
To get this result, we need modulus, modulusp and k such as R = 2^k, with
modulus * modulusp - R * R1 = GCD(modulus, R) = 1
*/
void montgomeryMultiplication (const BigInteger& other, const BigInteger& modulus,
const BigInteger& modulusp, int k);
/** Performs the Extended Euclidean algorithm.
This method will set the xOut and yOut arguments such that (a * xOut) - (b * yOut) = GCD (a, b).
On return, this object is left containing the value of the GCD.
*/
void extendedEuclidean (const BigInteger& a, const BigInteger& b,
BigInteger& xOut, BigInteger& yOut);
//==============================================================================
/** 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 (StringRef 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:
//==============================================================================
enum { numPreallocatedInts = 4 };
HeapBlock<uint32> heapAllocation;
uint32 preallocated[numPreallocatedInts];
size_t allocatedSize;
int highestBit = -1;
bool negative = false;
uint32* getValues() const noexcept;
uint32* ensureSize (size_t);
void shiftLeft (int bits, int startBit);
void shiftRight (int bits, int startBit);
JUCE_LEAK_DETECTOR (BigInteger)
};
/** Writes a BigInteger to an OutputStream as a UTF8 decimal string. */
OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const BigInteger& value);
} // namespace juce

File diff suppressed because it is too large Load Diff

View File

@ -1,251 +1,251 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. 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.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
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.
@tags{Core}
*/
class JUCE_API Expression
{
public:
//==============================================================================
/** Creates a simple expression with a value of 0. */
Expression();
/** Destructor. */
~Expression();
/** Creates a copy of an expression. */
Expression (const Expression&);
/** Copies another expression. */
Expression& operator= (const Expression&);
/** Move constructor */
Expression (Expression&&) noexcept;
/** Move assignment operator */
Expression& operator= (Expression&&) noexcept;
/** Creates a simple expression with a specified constant value. */
explicit Expression (double constant);
/** Attempts to create an expression by parsing a string.
Any errors are returned in the parseError argument provided.
*/
Expression (const String& stringToParse, String& parseError);
/** Returns a string version of the expression. */
String toString() const;
/** Returns an expression which is an addition operation of two existing expressions. */
Expression operator+ (const Expression&) const;
/** Returns an expression which is a subtraction operation of two existing expressions. */
Expression operator- (const Expression&) const;
/** Returns an expression which is a multiplication operation of two existing expressions. */
Expression operator* (const Expression&) const;
/** Returns an expression which is a division operation of two existing expressions. */
Expression operator/ (const Expression&) 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 parsing, the parseError argument will be set
to a description of the problem.
*/
static Expression parse (String::CharPointerType& stringToParse, String& parseError);
//==============================================================================
/** When evaluating an Expression object, this class is used to resolve symbols and
perform functions that the expression uses.
*/
class JUCE_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() = default;
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;
//==============================================================================
/** 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;
ReferenceCountedObjectPtr<Term> term;
explicit Expression (Term*);
};
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. 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.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
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.
@tags{Core}
*/
class JUCE_API Expression
{
public:
//==============================================================================
/** Creates a simple expression with a value of 0. */
Expression();
/** Destructor. */
~Expression();
/** Creates a copy of an expression. */
Expression (const Expression&);
/** Copies another expression. */
Expression& operator= (const Expression&);
/** Move constructor */
Expression (Expression&&) noexcept;
/** Move assignment operator */
Expression& operator= (Expression&&) noexcept;
/** Creates a simple expression with a specified constant value. */
explicit Expression (double constant);
/** Attempts to create an expression by parsing a string.
Any errors are returned in the parseError argument provided.
*/
Expression (const String& stringToParse, String& parseError);
/** Returns a string version of the expression. */
String toString() const;
/** Returns an expression which is an addition operation of two existing expressions. */
Expression operator+ (const Expression&) const;
/** Returns an expression which is a subtraction operation of two existing expressions. */
Expression operator- (const Expression&) const;
/** Returns an expression which is a multiplication operation of two existing expressions. */
Expression operator* (const Expression&) const;
/** Returns an expression which is a division operation of two existing expressions. */
Expression operator/ (const Expression&) 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 parsing, the parseError argument will be set
to a description of the problem.
*/
static Expression parse (String::CharPointerType& stringToParse, String& parseError);
//==============================================================================
/** When evaluating an Expression object, this class is used to resolve symbols and
perform functions that the expression uses.
*/
class JUCE_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() = default;
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;
//==============================================================================
/** 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;
ReferenceCountedObjectPtr<Term> term;
explicit Expression (Term*);
};
} // namespace juce

File diff suppressed because it is too large Load Diff

View File

@ -1,261 +1,261 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. 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.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
Represents a mapping between an arbitrary range of values and a
normalised 0->1 range.
The properties of the mapping also include an optional snapping interval
and skew-factor.
@see Range
@tags{Core}
*/
template <typename ValueType>
class NormalisableRange
{
public:
/** Creates a continuous range that performs a dummy mapping. */
NormalisableRange() = default;
NormalisableRange (const NormalisableRange&) = default;
NormalisableRange& operator= (const NormalisableRange&) = default;
NormalisableRange (NormalisableRange&&) = default;
NormalisableRange& operator= (NormalisableRange&&) = default;
/** Creates a NormalisableRange with a given range, interval and skew factor. */
NormalisableRange (ValueType rangeStart,
ValueType rangeEnd,
ValueType intervalValue,
ValueType skewFactor,
bool useSymmetricSkew = false) noexcept
: start (rangeStart), end (rangeEnd), interval (intervalValue),
skew (skewFactor), symmetricSkew (useSymmetricSkew)
{
checkInvariants();
}
/** Creates a NormalisableRange with a given range, continuous interval, but a dummy skew-factor. */
NormalisableRange (ValueType rangeStart,
ValueType rangeEnd) noexcept
: start (rangeStart), end (rangeEnd)
{
checkInvariants();
}
/** Creates a NormalisableRange with a given range and interval, but a dummy skew-factor. */
NormalisableRange (ValueType rangeStart,
ValueType rangeEnd,
ValueType intervalValue) noexcept
: start (rangeStart), end (rangeEnd), interval (intervalValue)
{
checkInvariants();
}
/** Creates a NormalisableRange with a given range, continuous interval, but a dummy skew-factor. */
NormalisableRange (Range<ValueType> range) noexcept
: NormalisableRange (range.getStart(), range.getEnd())
{
}
/** Creates a NormalisableRange with a given range and interval, but a dummy skew-factor. */
NormalisableRange (Range<ValueType> range, ValueType intervalValue) noexcept
: NormalisableRange (range.getStart(), range.getEnd(), intervalValue)
{
}
/** A function object which can remap a value in some way based on the start and end of a range. */
using ValueRemapFunction = std::function<ValueType(ValueType rangeStart,
ValueType rangeEnd,
ValueType valueToRemap)>;
/** Creates a NormalisableRange with a given range and an injective mapping function.
@param rangeStart The minimum value in the range.
@param rangeEnd The maximum value in the range.
@param convertFrom0To1Func A function which uses the current start and end of this NormalisableRange
and produces a mapped value from a normalised value.
@param convertTo0To1Func A function which uses the current start and end of this NormalisableRange
and produces a normalised value from a mapped value.
@param snapToLegalValueFunc A function which uses the current start and end of this NormalisableRange
to take a mapped value and snap it to the nearest legal value.
*/
NormalisableRange (ValueType rangeStart,
ValueType rangeEnd,
ValueRemapFunction convertFrom0To1Func,
ValueRemapFunction convertTo0To1Func,
ValueRemapFunction snapToLegalValueFunc = {}) noexcept
: start (rangeStart),
end (rangeEnd),
convertFrom0To1Function (std::move (convertFrom0To1Func)),
convertTo0To1Function (std::move (convertTo0To1Func)),
snapToLegalValueFunction (std::move (snapToLegalValueFunc))
{
checkInvariants();
}
/** Uses the properties of this mapping to convert a non-normalised value to
its 0->1 representation.
*/
ValueType convertTo0to1 (ValueType v) const noexcept
{
if (convertTo0To1Function != nullptr)
return clampTo0To1 (convertTo0To1Function (start, end, v));
auto proportion = clampTo0To1 ((v - start) / (end - start));
if (skew == static_cast<ValueType> (1))
return proportion;
if (! symmetricSkew)
return std::pow (proportion, skew);
auto distanceFromMiddle = static_cast<ValueType> (2) * proportion - static_cast<ValueType> (1);
return (static_cast<ValueType> (1) + std::pow (std::abs (distanceFromMiddle), skew)
* (distanceFromMiddle < ValueType() ? static_cast<ValueType> (-1)
: static_cast<ValueType> (1)))
/ static_cast<ValueType> (2);
}
/** Uses the properties of this mapping to convert a normalised 0->1 value to
its full-range representation.
*/
ValueType convertFrom0to1 (ValueType proportion) const noexcept
{
proportion = clampTo0To1 (proportion);
if (convertFrom0To1Function != nullptr)
return convertFrom0To1Function (start, end, proportion);
if (! symmetricSkew)
{
if (skew != static_cast<ValueType> (1) && proportion > ValueType())
proportion = std::exp (std::log (proportion) / skew);
return start + (end - start) * proportion;
}
auto distanceFromMiddle = static_cast<ValueType> (2) * proportion - static_cast<ValueType> (1);
if (skew != static_cast<ValueType> (1) && distanceFromMiddle != static_cast<ValueType> (0))
distanceFromMiddle = std::exp (std::log (std::abs (distanceFromMiddle)) / skew)
* (distanceFromMiddle < ValueType() ? static_cast<ValueType> (-1)
: static_cast<ValueType> (1));
return start + (end - start) / static_cast<ValueType> (2) * (static_cast<ValueType> (1) + distanceFromMiddle);
}
/** Takes a non-normalised value and snaps it based on either the interval property of
this NormalisableRange or the lambda function supplied to the constructor.
*/
ValueType snapToLegalValue (ValueType v) const noexcept
{
if (snapToLegalValueFunction != nullptr)
return snapToLegalValueFunction (start, end, v);
if (interval > ValueType())
v = start + interval * std::floor ((v - start) / interval + static_cast<ValueType> (0.5));
return (v <= start || end <= start) ? start : (v >= end ? end : v);
}
/** Returns the extent of the normalisable range. */
Range<ValueType> getRange() const noexcept { return { start, end }; }
/** Given a value which is between the start and end points, this sets the skew
such that convertFrom0to1 (0.5) will return this value.
If you have used lambda functions for convertFrom0to1Func and convertFrom0to1Func in the
constructor of this class then the skew value is ignored.
@param centrePointValue this must be greater than the start of the range and less than the end.
*/
void setSkewForCentre (ValueType centrePointValue) noexcept
{
jassert (centrePointValue > start);
jassert (centrePointValue < end);
symmetricSkew = false;
skew = std::log (static_cast<ValueType> (0.5)) / std::log ((centrePointValue - start) / (end - start));
checkInvariants();
}
/** The minimum value of the non-normalised range. */
ValueType start = 0;
/** The maximum value of the non-normalised range. */
ValueType end = 1;
/** The snapping interval that should be used (for a non-normalised value). Use 0 for a
continuous range.
If you have used a lambda function for snapToLegalValueFunction in the constructor of
this class then the interval is ignored.
*/
ValueType interval = 0;
/** An optional skew factor that alters the way values are distribute across the range.
The skew factor lets you skew the mapping logarithmically so that larger or smaller
values are given a larger proportion of the available space.
A factor of 1.0 has no skewing effect at all. If the factor is < 1.0, the lower end
of the range will fill more of the slider's length; if the factor is > 1.0, the upper
end of the range will be expanded.
If you have used lambda functions for convertFrom0to1Func and convertFrom0to1Func in the
constructor of this class then the skew value is ignored.
*/
ValueType skew = 1;
/** If true, the skew factor applies from the middle of the slider to each of its ends. */
bool symmetricSkew = false;
private:
void checkInvariants() const
{
jassert (end > start);
jassert (interval >= ValueType());
jassert (skew > ValueType());
}
static ValueType clampTo0To1 (ValueType value)
{
auto clampedValue = jlimit (static_cast<ValueType> (0), static_cast<ValueType> (1), value);
// If you hit this assertion then either your normalisation function is not working
// correctly or your input is out of the expected bounds.
jassert (clampedValue == value);
return clampedValue;
}
ValueRemapFunction convertFrom0To1Function, convertTo0To1Function, snapToLegalValueFunction;
};
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. 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.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
Represents a mapping between an arbitrary range of values and a
normalised 0->1 range.
The properties of the mapping also include an optional snapping interval
and skew-factor.
@see Range
@tags{Core}
*/
template <typename ValueType>
class NormalisableRange
{
public:
/** Creates a continuous range that performs a dummy mapping. */
NormalisableRange() = default;
NormalisableRange (const NormalisableRange&) = default;
NormalisableRange& operator= (const NormalisableRange&) = default;
NormalisableRange (NormalisableRange&&) = default;
NormalisableRange& operator= (NormalisableRange&&) = default;
/** Creates a NormalisableRange with a given range, interval and skew factor. */
NormalisableRange (ValueType rangeStart,
ValueType rangeEnd,
ValueType intervalValue,
ValueType skewFactor,
bool useSymmetricSkew = false) noexcept
: start (rangeStart), end (rangeEnd), interval (intervalValue),
skew (skewFactor), symmetricSkew (useSymmetricSkew)
{
checkInvariants();
}
/** Creates a NormalisableRange with a given range, continuous interval, but a dummy skew-factor. */
NormalisableRange (ValueType rangeStart,
ValueType rangeEnd) noexcept
: start (rangeStart), end (rangeEnd)
{
checkInvariants();
}
/** Creates a NormalisableRange with a given range and interval, but a dummy skew-factor. */
NormalisableRange (ValueType rangeStart,
ValueType rangeEnd,
ValueType intervalValue) noexcept
: start (rangeStart), end (rangeEnd), interval (intervalValue)
{
checkInvariants();
}
/** Creates a NormalisableRange with a given range, continuous interval, but a dummy skew-factor. */
NormalisableRange (Range<ValueType> range) noexcept
: NormalisableRange (range.getStart(), range.getEnd())
{
}
/** Creates a NormalisableRange with a given range and interval, but a dummy skew-factor. */
NormalisableRange (Range<ValueType> range, ValueType intervalValue) noexcept
: NormalisableRange (range.getStart(), range.getEnd(), intervalValue)
{
}
/** A function object which can remap a value in some way based on the start and end of a range. */
using ValueRemapFunction = std::function<ValueType(ValueType rangeStart,
ValueType rangeEnd,
ValueType valueToRemap)>;
/** Creates a NormalisableRange with a given range and an injective mapping function.
@param rangeStart The minimum value in the range.
@param rangeEnd The maximum value in the range.
@param convertFrom0To1Func A function which uses the current start and end of this NormalisableRange
and produces a mapped value from a normalised value.
@param convertTo0To1Func A function which uses the current start and end of this NormalisableRange
and produces a normalised value from a mapped value.
@param snapToLegalValueFunc A function which uses the current start and end of this NormalisableRange
to take a mapped value and snap it to the nearest legal value.
*/
NormalisableRange (ValueType rangeStart,
ValueType rangeEnd,
ValueRemapFunction convertFrom0To1Func,
ValueRemapFunction convertTo0To1Func,
ValueRemapFunction snapToLegalValueFunc = {}) noexcept
: start (rangeStart),
end (rangeEnd),
convertFrom0To1Function (std::move (convertFrom0To1Func)),
convertTo0To1Function (std::move (convertTo0To1Func)),
snapToLegalValueFunction (std::move (snapToLegalValueFunc))
{
checkInvariants();
}
/** Uses the properties of this mapping to convert a non-normalised value to
its 0->1 representation.
*/
ValueType convertTo0to1 (ValueType v) const noexcept
{
if (convertTo0To1Function != nullptr)
return clampTo0To1 (convertTo0To1Function (start, end, v));
auto proportion = clampTo0To1 ((v - start) / (end - start));
if (skew == static_cast<ValueType> (1))
return proportion;
if (! symmetricSkew)
return std::pow (proportion, skew);
auto distanceFromMiddle = static_cast<ValueType> (2) * proportion - static_cast<ValueType> (1);
return (static_cast<ValueType> (1) + std::pow (std::abs (distanceFromMiddle), skew)
* (distanceFromMiddle < ValueType() ? static_cast<ValueType> (-1)
: static_cast<ValueType> (1)))
/ static_cast<ValueType> (2);
}
/** Uses the properties of this mapping to convert a normalised 0->1 value to
its full-range representation.
*/
ValueType convertFrom0to1 (ValueType proportion) const noexcept
{
proportion = clampTo0To1 (proportion);
if (convertFrom0To1Function != nullptr)
return convertFrom0To1Function (start, end, proportion);
if (! symmetricSkew)
{
if (skew != static_cast<ValueType> (1) && proportion > ValueType())
proportion = std::exp (std::log (proportion) / skew);
return start + (end - start) * proportion;
}
auto distanceFromMiddle = static_cast<ValueType> (2) * proportion - static_cast<ValueType> (1);
if (skew != static_cast<ValueType> (1) && distanceFromMiddle != static_cast<ValueType> (0))
distanceFromMiddle = std::exp (std::log (std::abs (distanceFromMiddle)) / skew)
* (distanceFromMiddle < ValueType() ? static_cast<ValueType> (-1)
: static_cast<ValueType> (1));
return start + (end - start) / static_cast<ValueType> (2) * (static_cast<ValueType> (1) + distanceFromMiddle);
}
/** Takes a non-normalised value and snaps it based on either the interval property of
this NormalisableRange or the lambda function supplied to the constructor.
*/
ValueType snapToLegalValue (ValueType v) const noexcept
{
if (snapToLegalValueFunction != nullptr)
return snapToLegalValueFunction (start, end, v);
if (interval > ValueType())
v = start + interval * std::floor ((v - start) / interval + static_cast<ValueType> (0.5));
return (v <= start || end <= start) ? start : (v >= end ? end : v);
}
/** Returns the extent of the normalisable range. */
Range<ValueType> getRange() const noexcept { return { start, end }; }
/** Given a value which is between the start and end points, this sets the skew
such that convertFrom0to1 (0.5) will return this value.
If you have used lambda functions for convertFrom0to1Func and convertFrom0to1Func in the
constructor of this class then the skew value is ignored.
@param centrePointValue this must be greater than the start of the range and less than the end.
*/
void setSkewForCentre (ValueType centrePointValue) noexcept
{
jassert (centrePointValue > start);
jassert (centrePointValue < end);
symmetricSkew = false;
skew = std::log (static_cast<ValueType> (0.5)) / std::log ((centrePointValue - start) / (end - start));
checkInvariants();
}
/** The minimum value of the non-normalised range. */
ValueType start = 0;
/** The maximum value of the non-normalised range. */
ValueType end = 1;
/** The snapping interval that should be used (for a non-normalised value). Use 0 for a
continuous range.
If you have used a lambda function for snapToLegalValueFunction in the constructor of
this class then the interval is ignored.
*/
ValueType interval = 0;
/** An optional skew factor that alters the way values are distribute across the range.
The skew factor lets you skew the mapping logarithmically so that larger or smaller
values are given a larger proportion of the available space.
A factor of 1.0 has no skewing effect at all. If the factor is < 1.0, the lower end
of the range will fill more of the slider's length; if the factor is > 1.0, the upper
end of the range will be expanded.
If you have used lambda functions for convertFrom0to1Func and convertFrom0to1Func in the
constructor of this class then the skew value is ignored.
*/
ValueType skew = 1;
/** If true, the skew factor applies from the middle of the slider to each of its ends. */
bool symmetricSkew = false;
private:
void checkInvariants() const
{
jassert (end > start);
jassert (interval >= ValueType());
jassert (skew > ValueType());
}
static ValueType clampTo0To1 (ValueType value)
{
auto clampedValue = jlimit (static_cast<ValueType> (0), static_cast<ValueType> (1), value);
// If you hit this assertion then either your normalisation function is not working
// correctly or your input is out of the expected bounds.
jassert (clampedValue == value);
return clampedValue;
}
ValueRemapFunction convertFrom0To1Function, convertTo0To1Function, snapToLegalValueFunction;
};
} // namespace juce

View File

@ -1,204 +1,200 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. 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.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
Random::Random (int64 seedValue) noexcept : seed (seedValue)
{
}
Random::Random() : seed (1)
{
setSeedRandomly();
}
Random::~Random() noexcept
{
}
void Random::setSeed (const int64 newSeed) noexcept
{
if (this == &getSystemRandom())
{
// Resetting the system Random risks messing up
// JUCE's internal state. If you need a predictable
// stream of random numbers you should use a local
// Random object.
jassertfalse;
return;
}
seed = newSeed;
}
void Random::combineSeed (const int64 seedValue) noexcept
{
seed ^= nextInt64() ^ seedValue;
}
void Random::setSeedRandomly()
{
static std::atomic<int64> globalSeed { 0 };
combineSeed (globalSeed ^ (int64) (pointer_sized_int) this);
combineSeed (Time::getMillisecondCounter());
combineSeed (Time::getHighResolutionTicks());
combineSeed (Time::getHighResolutionTicksPerSecond());
combineSeed (Time::currentTimeMillis());
globalSeed ^= seed;
}
Random& Random::getSystemRandom() noexcept
{
static Random sysRand;
return sysRand;
}
//==============================================================================
int Random::nextInt() noexcept
{
seed = (int64) (((((uint64) seed) * 0x5deece66dLL) + 11) & 0xffffffffffffLL);
return (int) (seed >> 16);
}
int Random::nextInt (const int maxValue) noexcept
{
jassert (maxValue > 0);
return (int) ((((unsigned int) nextInt()) * (uint64) maxValue) >> 32);
}
int Random::nextInt (Range<int> range) noexcept
{
return range.getStart() + nextInt (range.getLength());
}
int64 Random::nextInt64() noexcept
{
return (int64) ((((uint64) (unsigned int) nextInt()) << 32) | (uint64) (unsigned int) nextInt());
}
bool Random::nextBool() noexcept
{
return (nextInt() & 0x40000000) != 0;
}
float Random::nextFloat() noexcept
{
auto result = static_cast<float> (static_cast<uint32> (nextInt()))
/ (static_cast<float> (std::numeric_limits<uint32>::max()) + 1.0f);
return result == 1.0f ? 1.0f - std::numeric_limits<float>::epsilon() : result;
}
double Random::nextDouble() noexcept
{
return static_cast<uint32> (nextInt()) / (std::numeric_limits<uint32>::max() + 1.0);
}
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());
}
//==============================================================================
//==============================================================================
#if JUCE_UNIT_TESTS
class RandomTests : public UnitTest
{
public:
RandomTests()
: UnitTest ("Random", UnitTestCategories::maths)
{}
void runTest() override
{
beginTest ("Random");
Random r = getRandom();
for (int i = 2000; --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;
#endif
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. 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.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
Random::Random (int64 seedValue) noexcept : seed (seedValue)
{
}
Random::Random() : seed (1)
{
setSeedRandomly();
}
void Random::setSeed (const int64 newSeed) noexcept
{
if (this == &getSystemRandom())
{
// Resetting the system Random risks messing up
// JUCE's internal state. If you need a predictable
// stream of random numbers you should use a local
// Random object.
jassertfalse;
return;
}
seed = newSeed;
}
void Random::combineSeed (const int64 seedValue) noexcept
{
seed ^= nextInt64() ^ seedValue;
}
void Random::setSeedRandomly()
{
static std::atomic<int64> globalSeed { 0 };
combineSeed (globalSeed ^ (int64) (pointer_sized_int) this);
combineSeed (Time::getMillisecondCounter());
combineSeed (Time::getHighResolutionTicks());
combineSeed (Time::getHighResolutionTicksPerSecond());
combineSeed (Time::currentTimeMillis());
globalSeed ^= seed;
}
Random& Random::getSystemRandom() noexcept
{
static Random sysRand;
return sysRand;
}
//==============================================================================
int Random::nextInt() noexcept
{
seed = (int64) (((((uint64) seed) * 0x5deece66dLL) + 11) & 0xffffffffffffLL);
return (int) (seed >> 16);
}
int Random::nextInt (const int maxValue) noexcept
{
jassert (maxValue > 0);
return (int) ((((unsigned int) nextInt()) * (uint64) maxValue) >> 32);
}
int Random::nextInt (Range<int> range) noexcept
{
return range.getStart() + nextInt (range.getLength());
}
int64 Random::nextInt64() noexcept
{
return (int64) ((((uint64) (unsigned int) nextInt()) << 32) | (uint64) (unsigned int) nextInt());
}
bool Random::nextBool() noexcept
{
return (nextInt() & 0x40000000) != 0;
}
float Random::nextFloat() noexcept
{
auto result = static_cast<float> (static_cast<uint32> (nextInt()))
/ (static_cast<float> (std::numeric_limits<uint32>::max()) + 1.0f);
return result == 1.0f ? 1.0f - std::numeric_limits<float>::epsilon() : result;
}
double Random::nextDouble() noexcept
{
return static_cast<uint32> (nextInt()) / (std::numeric_limits<uint32>::max() + 1.0);
}
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());
}
//==============================================================================
//==============================================================================
#if JUCE_UNIT_TESTS
class RandomTests : public UnitTest
{
public:
RandomTests()
: UnitTest ("Random", UnitTestCategories::maths)
{}
void runTest() override
{
beginTest ("Random");
Random r = getRandom();
for (int i = 2000; --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;
#endif
} // namespace juce

View File

@ -1,137 +1,134 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. 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.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A random number generator.
You can create a Random object and use it to generate a sequence of random numbers.
@tags{Core}
*/
class JUCE_API Random final
{
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 random number, limited to a given range.
@returns a random integer between the range start (inclusive) and its end (exclusive).
*/
int nextInt (Range<int> range) 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 (inclusive) to 1.0 (exclusive)
*/
float nextFloat() noexcept;
/** Returns the next random floating-point number.
@returns a random value in the range 0 (inclusive) to 1.0 (exclusive)
*/
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;
/** Returns the RNG's current seed. */
int64 getSeed() const noexcept { return seed; }
/** 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;
JUCE_LEAK_DETECTOR (Random)
};
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. 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.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A random number generator.
You can create a Random object and use it to generate a sequence of random numbers.
@tags{Core}
*/
class JUCE_API Random final
{
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();
/** 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 random number, limited to a given range.
@returns a random integer between the range start (inclusive) and its end (exclusive).
*/
int nextInt (Range<int> range) 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 (inclusive) to 1.0 (exclusive)
*/
float nextFloat() noexcept;
/** Returns the next random floating-point number.
@returns a random value in the range 0 (inclusive) to 1.0 (exclusive)
*/
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;
/** Returns the RNG's current seed. */
int64 getSeed() const noexcept { return seed; }
/** 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;
JUCE_LEAK_DETECTOR (Random)
};
} // namespace juce

View File

@ -1,297 +1,298 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. 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.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/** A general-purpose range object, that simply represents any linear range with
a start and end point.
Note that when checking whether values fall within the range, the start value is
considered to be inclusive, and the end of the range exclusive.
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.
@tags{Core}
*/
template <typename ValueType>
class Range
{
public:
//==============================================================================
/** Constructs an empty range. */
constexpr Range() = default;
/** Constructs a range with given start and end values. */
constexpr Range (const ValueType startValue, const ValueType endValue) noexcept
: start (startValue), end (jmax (startValue, endValue))
{
}
/** Constructs a copy of another range. */
constexpr Range (const Range&) = default;
/** Copies another range object. */
Range& operator= (const Range&) = default;
/** Returns the range that lies between two positions (in either order). */
constexpr static Range between (const ValueType position1, const ValueType position2) noexcept
{
return position1 < position2 ? Range (position1, position2)
: Range (position2, position1);
}
/** Returns a range with a given start and length. */
static Range withStartAndLength (const ValueType startValue, const ValueType length) noexcept
{
jassert (length >= ValueType());
return Range (startValue, startValue + length);
}
/** Returns a range with the specified start position and a length of zero. */
constexpr static Range emptyRange (const ValueType start) noexcept
{
return Range (start, start);
}
//==============================================================================
/** Returns the start of the range. */
constexpr inline ValueType getStart() const noexcept { return start; }
/** Returns the length of the range. */
constexpr inline ValueType getLength() const noexcept { return end - start; }
/** Returns the end of the range. */
constexpr inline ValueType getEnd() const noexcept { return end; }
/** Returns true if the range has a length of zero. */
constexpr 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.
*/
constexpr Range withStart (const ValueType newStart) const noexcept
{
return Range (newStart, jmax (newStart, end));
}
/** Returns a range with the same length as this one, but moved to have the given start position. */
constexpr 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.
*/
constexpr Range withEnd (const ValueType newEnd) const noexcept
{
return Range (jmin (start, newEnd), newEnd);
}
/** Returns a range with the same length as this one, but moved to have the given end position. */
constexpr 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 + jmax (ValueType(), newLength);
}
/** Returns a range with the same start as this one, but a different length.
Lengths less than zero are treated as zero.
*/
constexpr Range withLength (const ValueType newLength) const noexcept
{
return Range (start, start + newLength);
}
/** Returns a range which has its start moved down and its end moved up by the
given amount.
@returns The returned range will be (start - amount, end + amount)
*/
constexpr Range expanded (ValueType amount) const noexcept
{
return Range (start - amount, end + amount);
}
//==============================================================================
/** 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.
*/
constexpr 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. */
constexpr Range operator- (const ValueType amountToSubtract) const noexcept
{
return Range (start - amountToSubtract, end - amountToSubtract);
}
constexpr bool operator== (Range other) const noexcept { return start == other.start && end == other.end; }
constexpr bool operator!= (Range other) const noexcept { return start != other.start || end != other.end; }
//==============================================================================
/** Returns true if the given position lies inside this range.
When making this comparison, the start value is considered to be inclusive,
and the end of the range exclusive.
*/
constexpr 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 jlimit (start, end, value);
}
/** Returns true if the given range lies entirely inside this range. */
constexpr bool contains (Range other) const noexcept
{
return start <= other.start && end >= other.end;
}
/** Returns true if the given range intersects this one. */
constexpr 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. */
constexpr Range getIntersectionWith (Range other) const noexcept
{
return Range (jmax (start, other.start),
jmin (end, other.end));
}
/** Returns the smallest range that contains both this one and the other one. */
constexpr Range getUnionWith (Range other) const noexcept
{
return Range (jmin (start, other.start),
jmax (end, other.end));
}
/** Returns the smallest range that contains both this one and the given value. */
constexpr Range getUnionWith (const ValueType valueToInclude) const noexcept
{
return Range (jmin (valueToInclude, start),
jmax (valueToInclude, 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 (jlimit (start, end - otherLen, rangeToConstrain.getStart()));
}
/** Scans an array of values for its min and max, and returns these as a Range. */
static Range findMinAndMax (const ValueType* values, int numValues) noexcept
{
if (numValues <= 0)
return Range();
const ValueType first (*values++);
Range r (first, first);
while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
{
const ValueType v (*values++);
if (r.end < v) r.end = v;
if (v < r.start) r.start = v;
}
return r;
}
private:
//==============================================================================
ValueType start{}, end{};
};
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. 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.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/** A general-purpose range object, that simply represents any linear range with
a start and end point.
Note that when checking whether values fall within the range, the start value is
considered to be inclusive, and the end of the range exclusive.
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.
@tags{Core}
*/
template <typename ValueType>
class Range
{
public:
//==============================================================================
/** Constructs an empty range. */
constexpr Range() = default;
/** Constructs a range with given start and end values. */
constexpr Range (const ValueType startValue, const ValueType endValue) noexcept
: start (startValue), end (jmax (startValue, endValue))
{
}
/** Constructs a copy of another range. */
constexpr Range (const Range&) = default;
/** Copies another range object. */
Range& operator= (const Range&) = default;
/** Returns the range that lies between two positions (in either order). */
constexpr static Range between (const ValueType position1, const ValueType position2) noexcept
{
return position1 < position2 ? Range (position1, position2)
: Range (position2, position1);
}
/** Returns a range with a given start and length. */
JUCE_NODISCARD static Range withStartAndLength (const ValueType startValue, const ValueType length) noexcept
{
jassert (length >= ValueType());
return Range (startValue, startValue + length);
}
/** Returns a range with the specified start position and a length of zero. */
JUCE_NODISCARD constexpr static Range emptyRange (const ValueType start) noexcept
{
return Range (start, start);
}
//==============================================================================
/** Returns the start of the range. */
constexpr inline ValueType getStart() const noexcept { return start; }
/** Returns the length of the range. */
constexpr inline ValueType getLength() const noexcept { return end - start; }
/** Returns the end of the range. */
constexpr inline ValueType getEnd() const noexcept { return end; }
/** Returns true if the range has a length of zero. */
constexpr 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.
*/
JUCE_NODISCARD constexpr Range withStart (const ValueType newStart) const noexcept
{
return Range (newStart, jmax (newStart, end));
}
/** Returns a range with the same length as this one, but moved to have the given start position. */
JUCE_NODISCARD constexpr 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.
*/
JUCE_NODISCARD constexpr Range withEnd (const ValueType newEnd) const noexcept
{
return Range (jmin (start, newEnd), newEnd);
}
/** Returns a range with the same length as this one, but moved to have the given end position. */
JUCE_NODISCARD constexpr 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 + jmax (ValueType(), newLength);
}
/** Returns a range with the same start as this one, but a different length.
Lengths less than zero are treated as zero.
*/
JUCE_NODISCARD constexpr Range withLength (const ValueType newLength) const noexcept
{
return Range (start, start + newLength);
}
/** Returns a range which has its start moved down and its end moved up by the
given amount.
@returns The returned range will be (start - amount, end + amount)
*/
JUCE_NODISCARD constexpr Range expanded (ValueType amount) const noexcept
{
return Range (start - amount, end + amount);
}
//==============================================================================
/** 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.
*/
constexpr 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. */
constexpr Range operator- (const ValueType amountToSubtract) const noexcept
{
return Range (start - amountToSubtract, end - amountToSubtract);
}
constexpr bool operator== (Range other) const noexcept { return start == other.start && end == other.end; }
constexpr bool operator!= (Range other) const noexcept { return start != other.start || end != other.end; }
//==============================================================================
/** Returns true if the given position lies inside this range.
When making this comparison, the start value is considered to be inclusive,
and the end of the range exclusive.
*/
constexpr 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 jlimit (start, end, value);
}
/** Returns true if the given range lies entirely inside this range. */
constexpr bool contains (Range other) const noexcept
{
return start <= other.start && end >= other.end;
}
/** Returns true if the given range intersects this one. */
constexpr 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. */
JUCE_NODISCARD constexpr Range getIntersectionWith (Range other) const noexcept
{
return Range (jmax (start, other.start),
jmin (end, other.end));
}
/** Returns the smallest range that contains both this one and the other one. */
JUCE_NODISCARD constexpr Range getUnionWith (Range other) const noexcept
{
return Range (jmin (start, other.start),
jmax (end, other.end));
}
/** Returns the smallest range that contains both this one and the given value. */
JUCE_NODISCARD constexpr Range getUnionWith (const ValueType valueToInclude) const noexcept
{
return Range (jmin (valueToInclude, start),
jmax (valueToInclude, 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 (jlimit (start, end - otherLen, rangeToConstrain.getStart()));
}
/** Scans an array of values for its min and max, and returns these as a Range. */
template <typename Integral, std::enable_if_t<std::is_integral<Integral>::value, int> = 0>
static Range findMinAndMax (const ValueType* values, Integral numValues) noexcept
{
if (numValues <= 0)
return Range();
const ValueType first (*values++);
Range r (first, first);
while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
{
const ValueType v (*values++);
if (r.end < v) r.end = v;
if (v < r.start) r.start = v;
}
return r;
}
private:
//==============================================================================
ValueType start{}, end{};
};
} // namespace juce

View File

@ -1,136 +1,136 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. 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.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A class that measures various statistics about a series of floating point
values that it is given.
@tags{Core}
*/
template <typename FloatType>
class StatisticsAccumulator
{
public:
//==============================================================================
/** Constructs a new StatisticsAccumulator. */
StatisticsAccumulator() = default;
//==============================================================================
/** Add a new value to the accumulator.
This will update all running statistics accordingly.
*/
void addValue (FloatType v) noexcept
{
jassert (juce_isfinite (v));
sum += v;
sumSquares += v * v;
++count;
if (v > maximum) maximum = v;
if (v < minimum) minimum = v;
}
/** Reset the accumulator.
This will reset all currently saved statistcs.
*/
void reset() noexcept { *this = StatisticsAccumulator<FloatType>(); }
//==============================================================================
/** Returns the average (arithmetic mean) of all previously added values.
If no values have been added yet, this will return zero.
*/
FloatType getAverage() const noexcept
{
return count > 0 ? sum / (FloatType) count
: FloatType();
}
/** Returns the variance of all previously added values.
If no values have been added yet, this will return zero.
*/
FloatType getVariance() const noexcept
{
return count > 0 ? (sumSquares - sum * sum / (FloatType) count) / (FloatType) count
: FloatType();
}
/** Returns the standard deviation of all previously added values.
If no values have been added yet, this will return zero.
*/
FloatType getStandardDeviation() const noexcept
{
return std::sqrt (getVariance());
}
/** Returns the smallest of all previously added values.
If no values have been added yet, this will return positive infinity.
*/
FloatType getMinValue() const noexcept
{
return minimum;
}
/** Returns the largest of all previously added values.
If no values have been added yet, this will return negative infinity.
*/
FloatType getMaxValue() const noexcept
{
return maximum;
}
/** Returns how many values have been added to this accumulator. */
size_t getCount() const noexcept
{
return count;
}
private:
//==============================================================================
struct KahanSum
{
KahanSum() = default;
operator FloatType() const noexcept { return sum; }
void JUCE_NO_ASSOCIATIVE_MATH_OPTIMISATIONS operator+= (FloatType value) noexcept
{
FloatType correctedValue = value - error;
FloatType newSum = sum + correctedValue;
error = (newSum - sum) - correctedValue;
sum = newSum;
}
FloatType sum{}, error{};
};
//==============================================================================
size_t count { 0 };
KahanSum sum, sumSquares;
FloatType minimum { std::numeric_limits<FloatType>::infinity() },
maximum { -std::numeric_limits<FloatType>::infinity() };
};
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. 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.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A class that measures various statistics about a series of floating point
values that it is given.
@tags{Core}
*/
template <typename FloatType>
class StatisticsAccumulator
{
public:
//==============================================================================
/** Constructs a new StatisticsAccumulator. */
StatisticsAccumulator() = default;
//==============================================================================
/** Add a new value to the accumulator.
This will update all running statistics accordingly.
*/
void addValue (FloatType v) noexcept
{
jassert (juce_isfinite (v));
sum += v;
sumSquares += v * v;
++count;
if (v > maximum) maximum = v;
if (v < minimum) minimum = v;
}
/** Reset the accumulator.
This will reset all currently saved statistcs.
*/
void reset() noexcept { *this = StatisticsAccumulator<FloatType>(); }
//==============================================================================
/** Returns the average (arithmetic mean) of all previously added values.
If no values have been added yet, this will return zero.
*/
FloatType getAverage() const noexcept
{
return count > 0 ? sum / (FloatType) count
: FloatType();
}
/** Returns the variance of all previously added values.
If no values have been added yet, this will return zero.
*/
FloatType getVariance() const noexcept
{
return count > 0 ? (sumSquares - sum * sum / (FloatType) count) / (FloatType) count
: FloatType();
}
/** Returns the standard deviation of all previously added values.
If no values have been added yet, this will return zero.
*/
FloatType getStandardDeviation() const noexcept
{
return std::sqrt (getVariance());
}
/** Returns the smallest of all previously added values.
If no values have been added yet, this will return positive infinity.
*/
FloatType getMinValue() const noexcept
{
return minimum;
}
/** Returns the largest of all previously added values.
If no values have been added yet, this will return negative infinity.
*/
FloatType getMaxValue() const noexcept
{
return maximum;
}
/** Returns how many values have been added to this accumulator. */
size_t getCount() const noexcept
{
return count;
}
private:
//==============================================================================
struct KahanSum
{
KahanSum() = default;
operator FloatType() const noexcept { return sum; }
void JUCE_NO_ASSOCIATIVE_MATH_OPTIMISATIONS operator+= (FloatType value) noexcept
{
FloatType correctedValue = value - error;
FloatType newSum = sum + correctedValue;
error = (newSum - sum) - correctedValue;
sum = newSum;
}
FloatType sum{}, error{};
};
//==============================================================================
size_t count { 0 };
KahanSum sum, sumSquares;
FloatType minimum { std::numeric_limits<FloatType>::infinity() },
maximum { -std::numeric_limits<FloatType>::infinity() };
};
} // namespace juce