#pragma once template <typename Type, size_t N> constexpr int numElementsInArray(Type (&)[N]) noexcept { return N; } /** Remaps a value from a source range to a target range. */ template <typename Type> Type jmap(Type sourceValue, Type sourceRangeMin, Type sourceRangeMax, Type targetRangeMin, Type targetRangeMax) { check(sourceRangeMax != sourceRangeMin); // mapping from a range of zero will produce NaN! return targetRangeMin + ((targetRangeMax - targetRangeMin) * (sourceValue - sourceRangeMin)) / (sourceRangeMax - sourceRangeMin); } template <typename FloatType> int RoundToInt(const FloatType value) noexcept { #ifdef __INTEL_COMPILER #pragma float_control (precise, on, push) #endif union { int asInt[2]; double asDouble; } n; n.asDouble = static_cast<double>(value) + 6755399441055744.0; #if JUCE_BIG_ENDIAN return n.asInt [1]; #else return n.asInt[0]; #endif } /** Returns true if a value is at least zero, and also below a specified upper limit. This is basically a quicker way to write: @code valueToTest >= 0 && valueToTest < upperLimit @endcode */ template <typename Type1, typename Type2> bool IsPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept { check(Type1() <= static_cast<Type1> (upperLimit)); // makes no sense to call this if the upper limit is itself below zero.. return Type1() <= valueToTest && valueToTest < static_cast<Type1>(upperLimit); } template <typename Type> bool IsPositiveAndBelow(int valueToTest, Type upperLimit) noexcept { check(upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero.. return static_cast<unsigned int>(valueToTest) < static_cast<unsigned int>(upperLimit); }