1 /*
2   ==============================================================================
3 
4    This file is part of the JUCE library.
5    Copyright (c) 2017 - ROLI Ltd.
6 
7    JUCE is an open source library subject to commercial or open-source
8    licensing.
9 
10    The code included in this file is provided under the terms of the ISC license
11    http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12    To use, copy, modify, and/or distribute this software for any purpose with or
13    without fee is hereby granted provided that the above copyright notice and
14    this permission notice appear in all copies.
15 
16    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18    DISCLAIMED.
19 
20   ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
26 //==============================================================================
27 /*
28     This file sets up some handy mathematical typdefs and functions.
29 */
30 
31 //==============================================================================
32 // Definitions for the int8, int16, int32, int64 and pointer_sized_int types.
33 
34 /** A platform-independent 8-bit signed integer type. */
35 using int8      = signed char;
36 /** A platform-independent 8-bit unsigned integer type. */
37 using uint8     = unsigned char;
38 /** A platform-independent 16-bit signed integer type. */
39 using int16     = signed short;
40 /** A platform-independent 16-bit unsigned integer type. */
41 using uint16    = unsigned short;
42 /** A platform-independent 32-bit signed integer type. */
43 using int32     = signed int;
44 /** A platform-independent 32-bit unsigned integer type. */
45 using uint32    = unsigned int;
46 
47 #if JUCE_MSVC
48   /** A platform-independent 64-bit integer type. */
49   using int64  = __int64;
50   /** A platform-independent 64-bit unsigned integer type. */
51   using uint64 = unsigned __int64;
52 #else
53   /** A platform-independent 64-bit integer type. */
54   using int64  = long long;
55   /** A platform-independent 64-bit unsigned integer type. */
56   using uint64 = unsigned long long;
57 #endif
58 
59 #ifndef DOXYGEN
60  /** A macro for creating 64-bit literals.
61      Historically, this was needed to support portability with MSVC6, and is kept here
62      so that old code will still compile, but nowadays every compiler will support the
63      LL and ULL suffixes, so you should use those in preference to this macro.
64  */
65  #define literal64bit(longLiteral)     (longLiteral##LL)
66 #endif
67 
68 #if JUCE_64BIT
69   /** A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it. */
70   using pointer_sized_int  = int64;
71   /** An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it. */
72   using pointer_sized_uint = uint64;
73 #elif JUCE_MSVC
74   /** A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it. */
75   using pointer_sized_int  = _W64 int;
76   /** An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it. */
77   using pointer_sized_uint = _W64 unsigned int;
78 #else
79 # include <cstdint>
80   /** A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it. */
81   using pointer_sized_int  = intptr_t;
82   /** An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it. */
83   using pointer_sized_uint = uintptr_t;
84 #endif
85 
86 #if JUCE_WINDOWS && ! JUCE_MINGW
87   using ssize_t = pointer_sized_int;
88 #endif
89 
90 //==============================================================================
91 // Some indispensable min/max functions
92 
93 /** Returns the larger of two values. */
94 template <typename Type>
jmax(Type a,Type b)95 JUCE_CONSTEXPR Type jmax (Type a, Type b)                                   { return a < b ? b : a; }
96 
97 /** Returns the larger of three values. */
98 template <typename Type>
jmax(Type a,Type b,Type c)99 JUCE_CONSTEXPR Type jmax (Type a, Type b, Type c)                           { return a < b ? (b < c ? c : b) : (a < c ? c : a); }
100 
101 /** Returns the larger of four values. */
102 template <typename Type>
jmax(Type a,Type b,Type c,Type d)103 JUCE_CONSTEXPR Type jmax (Type a, Type b, Type c, Type d)                   { return jmax (a, jmax (b, c, d)); }
104 
105 /** Returns the smaller of two values. */
106 template <typename Type>
jmin(Type a,Type b)107 JUCE_CONSTEXPR Type jmin (Type a, Type b)                                   { return b < a ? b : a; }
108 
109 /** Returns the smaller of three values. */
110 template <typename Type>
jmin(Type a,Type b,Type c)111 JUCE_CONSTEXPR Type jmin (Type a, Type b, Type c)                           { return b < a ? (c < b ? c : b) : (c < a ? c : a); }
112 
113 /** Returns the smaller of four values. */
114 template <typename Type>
jmin(Type a,Type b,Type c,Type d)115 JUCE_CONSTEXPR Type jmin (Type a, Type b, Type c, Type d)                   { return jmin (a, jmin (b, c, d)); }
116 
117 /** Remaps a normalised value (between 0 and 1) to a target range.
118     This effectively returns (targetRangeMin + value0To1 * (targetRangeMax - targetRangeMin)).
119 */
120 template <typename Type>
jmap(Type value0To1,Type targetRangeMin,Type targetRangeMax)121 JUCE_CONSTEXPR Type jmap (Type value0To1, Type targetRangeMin, Type targetRangeMax)
122 {
123     return targetRangeMin + value0To1 * (targetRangeMax - targetRangeMin);
124 }
125 
126 /** Remaps a value from a source range to a target range. */
127 template <typename Type>
jmap(Type sourceValue,Type sourceRangeMin,Type sourceRangeMax,Type targetRangeMin,Type targetRangeMax)128 Type jmap (Type sourceValue, Type sourceRangeMin, Type sourceRangeMax, Type targetRangeMin, Type targetRangeMax)
129 {
130     jassert (sourceRangeMax != sourceRangeMin); // mapping from a range of zero will produce NaN!
131     return targetRangeMin + ((targetRangeMax - targetRangeMin) * (sourceValue - sourceRangeMin)) / (sourceRangeMax - sourceRangeMin);
132 }
133 
134 /** Scans an array of values, returning the minimum value that it contains. */
135 template <typename Type>
findMinimum(const Type * data,int numValues)136 Type findMinimum (const Type* data, int numValues)
137 {
138     if (numValues <= 0)
139         return Type (0);
140 
141     auto result = *data++;
142 
143     while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
144     {
145         auto v = *data++;
146 
147         if (v < result)
148             result = v;
149     }
150 
151     return result;
152 }
153 
154 /** Scans an array of values, returning the maximum value that it contains. */
155 template <typename Type>
findMaximum(const Type * values,int numValues)156 Type findMaximum (const Type* values, int numValues)
157 {
158     if (numValues <= 0)
159         return Type (0);
160 
161     auto result = *values++;
162 
163     while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
164     {
165         auto v = *values++;
166 
167         if (result < v)
168             result = v;
169     }
170 
171     return result;
172 }
173 
174 /** Scans an array of values, returning the minimum and maximum values that it contains. */
175 template <typename Type>
findMinAndMax(const Type * values,int numValues,Type & lowest,Type & highest)176 void findMinAndMax (const Type* values, int numValues, Type& lowest, Type& highest)
177 {
178     if (numValues <= 0)
179     {
180         lowest = Type (0);
181         highest = Type (0);
182     }
183     else
184     {
185         auto mn = *values++;
186         auto mx = mn;
187 
188         while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
189         {
190             auto v = *values++;
191 
192             if (mx < v)  mx = v;
193             if (v < mn)  mn = v;
194         }
195 
196         lowest = mn;
197         highest = mx;
198     }
199 }
200 
201 //==============================================================================
202 /** Constrains a value to keep it within a given range.
203 
204     This will check that the specified value lies between the lower and upper bounds
205     specified, and if not, will return the nearest value that would be in-range. Effectively,
206     it's like calling jmax (lowerLimit, jmin (upperLimit, value)).
207 
208     Note that it expects that lowerLimit <= upperLimit. If this isn't true,
209     the results will be unpredictable.
210 
211     @param lowerLimit           the minimum value to return
212     @param upperLimit           the maximum value to return
213     @param valueToConstrain     the value to try to return
214     @returns    the closest value to valueToConstrain which lies between lowerLimit
215                 and upperLimit (inclusive)
216     @see jmin, jmax, jmap
217 */
218 template <typename Type>
jlimit(Type lowerLimit,Type upperLimit,Type valueToConstrain)219 Type jlimit (Type lowerLimit,
220              Type upperLimit,
221              Type valueToConstrain) noexcept
222 {
223     jassert (lowerLimit <= upperLimit); // if these are in the wrong order, results are unpredictable..
224 
225     return valueToConstrain < lowerLimit ? lowerLimit
226                                          : (upperLimit < valueToConstrain ? upperLimit
227                                                                           : valueToConstrain);
228 }
229 
230 /** Returns true if a value is at least zero, and also below a specified upper limit.
231     This is basically a quicker way to write:
232     @code valueToTest >= 0 && valueToTest < upperLimit
233     @endcode
234 */
235 template <typename Type1, typename Type2>
isPositiveAndBelow(Type1 valueToTest,Type2 upperLimit)236 bool isPositiveAndBelow (Type1 valueToTest, Type2 upperLimit) noexcept
237 {
238     jassert (Type1() <= static_cast<Type1> (upperLimit)); // makes no sense to call this if the upper limit is itself below zero..
239     return Type1() <= valueToTest && valueToTest < static_cast<Type1> (upperLimit);
240 }
241 
242 template <typename Type>
isPositiveAndBelow(int valueToTest,Type upperLimit)243 bool isPositiveAndBelow (int valueToTest, Type upperLimit) noexcept
244 {
245     jassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero..
246     return static_cast<unsigned int> (valueToTest) < static_cast<unsigned int> (upperLimit);
247 }
248 
249 /** Returns true if a value is at least zero, and also less than or equal to a specified upper limit.
250     This is basically a quicker way to write:
251     @code valueToTest >= 0 && valueToTest <= upperLimit
252     @endcode
253 */
254 template <typename Type1, typename Type2>
isPositiveAndNotGreaterThan(Type1 valueToTest,Type2 upperLimit)255 bool isPositiveAndNotGreaterThan (Type1 valueToTest, Type2 upperLimit) noexcept
256 {
257     jassert (Type1() <= static_cast<Type1> (upperLimit)); // makes no sense to call this if the upper limit is itself below zero..
258     return Type1() <= valueToTest && valueToTest <= static_cast<Type1> (upperLimit);
259 }
260 
261 template <typename Type>
isPositiveAndNotGreaterThan(int valueToTest,Type upperLimit)262 bool isPositiveAndNotGreaterThan (int valueToTest, Type upperLimit) noexcept
263 {
264     jassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero..
265     return static_cast<unsigned int> (valueToTest) <= static_cast<unsigned int> (upperLimit);
266 }
267 
268 /** Computes the absolute difference between two values and returns true if it is less than or equal
269     to a given tolerance, otherwise it returns false.
270 */
271 template <typename Type>
isWithin(Type a,Type b,Type tolerance)272 bool isWithin (Type a, Type b, Type tolerance) noexcept
273 {
274     return std::abs (a - b) <= tolerance;
275 }
276 
277 /** Returns true if the two numbers are approximately equal. This is useful for floating-point
278     and double comparisons.
279 */
280 template <typename Type>
approximatelyEqual(Type a,Type b)281 bool approximatelyEqual (Type a, Type b) noexcept
282 {
283     return std::abs (a - b) <= (std::numeric_limits<Type>::epsilon() * std::max (a, b))
284             || std::abs (a - b) < std::numeric_limits<Type>::min();
285 }
286 
287 //==============================================================================
288 /** Handy function for avoiding unused variables warning. */
289 template <typename... Types>
ignoreUnused(Types &&...)290 void ignoreUnused (Types&&...) noexcept {}
291 
292 /** Handy function for getting the number of elements in a simple const C array.
293     E.g.
294     @code
295     static int myArray[] = { 1, 2, 3 };
296 
297     int numElements = numElementsInArray (myArray) // returns 3
298     @endcode
299 */
300 template <typename Type, size_t N>
numElementsInArray(Type (&)[N])301 JUCE_CONSTEXPR int numElementsInArray (Type (&)[N]) noexcept     { return N; }
302 
303 //==============================================================================
304 // Some useful maths functions that aren't always present with all compilers and build settings.
305 
306 /** Using juce_hypot is easier than dealing with the different types of hypot function
307     that are provided by the various platforms and compilers. */
308 template <typename Type>
juce_hypot(Type a,Type b)309 Type juce_hypot (Type a, Type b) noexcept
310 {
311    #if JUCE_MSVC
312     return static_cast<Type> (_hypot (a, b));
313    #else
314     return static_cast<Type> (hypot (a, b));
315    #endif
316 }
317 
318 #ifndef DOXYGEN
319 template <>
juce_hypot(float a,float b)320 inline float juce_hypot (float a, float b) noexcept
321 {
322    #if JUCE_MSVC
323     return _hypotf (a, b);
324    #else
325     return hypotf (a, b);
326    #endif
327 }
328 #endif
329 
330 //==============================================================================
331 #if JUCE_HAS_CONSTEXPR
332 
333 /** Commonly used mathematical constants
334 
335     @tags{Core}
336 */
337 template <typename FloatType>
338 struct MathConstants
339 {
340     /** A predefined value for Pi */
341     static constexpr FloatType pi = static_cast<FloatType> (3.141592653589793238L);
342 
343     /** A predefined value for 2 * Pi */
344     static constexpr FloatType twoPi = static_cast<FloatType> (2 * 3.141592653589793238L);
345 
346     /** A predefined value for Pi / 2 */
347     static constexpr FloatType halfPi = static_cast<FloatType> (3.141592653589793238L / 2);
348 
349     /** A predefined value for Euler's number */
350     static constexpr FloatType euler = static_cast<FloatType> (2.71828182845904523536L);
351 
352     /** A predefined value for sqrt(2) */
353     static constexpr FloatType sqrt2 = static_cast<FloatType> (1.4142135623730950488L);
354 };
355 
356 #else
357 
358 /** Commonly used mathematical constants
359 
360     @tags{Core}
361 */
362 template <typename FloatType>
363 struct MathConstants
364 {
365     /** A predefined value for Pi */
366     static const FloatType pi;
367 
368     /** A predefined value for 2 * Pi */
369     static const FloatType twoPi;
370 
371     /** A predefined value for Pi / 2 */
372     static const FloatType halfPi;
373 
374     /** A predefined value for Euler's number */
375     static const FloatType euler;
376 
377     /** A predefined value for sqrt(2) */
378     static const FloatType sqrt2;
379 };
380 
381 template <typename FloatType>
382 const FloatType MathConstants<FloatType>::pi = static_cast<FloatType> (3.141592653589793238L);
383 
384 template <typename FloatType>
385 const FloatType MathConstants<FloatType>::twoPi = static_cast<FloatType> (2 * 3.141592653589793238L);
386 
387 template <typename FloatType>
388 const FloatType MathConstants<FloatType>::halfPi = static_cast<FloatType> (3.141592653589793238L / 2);
389 
390 template <typename FloatType>
391 const FloatType MathConstants<FloatType>::euler = static_cast<FloatType> (2.71828182845904523536L);
392 
393 template <typename FloatType>
394 const FloatType MathConstants<FloatType>::sqrt2 = static_cast<FloatType> (1.4142135623730950488L);
395 
396 #endif
397 
398 #ifndef DOXYGEN
399 /** A double-precision constant for pi.
400     @deprecated This is deprecated in favour of MathConstants<double>::pi.
401     The reason is that "double_Pi" was a confusing name, and many people misused it,
402     wrongly thinking it meant 2 * pi !
403 */
404 const JUCE_CONSTEXPR double  double_Pi  = MathConstants<double>::pi;
405 
406 /** A single-precision constant for pi.
407     @deprecated This is deprecated in favour of MathConstants<float>::pi.
408     The reason is that "double_Pi" was a confusing name, and many people misused it,
409     wrongly thinking it meant 2 * pi !
410 */
411 const JUCE_CONSTEXPR float   float_Pi   = MathConstants<float>::pi;
412 #endif
413 
414 /** Converts an angle in degrees to radians. */
415 template <typename FloatType>
degreesToRadians(FloatType degrees)416 JUCE_CONSTEXPR FloatType degreesToRadians (FloatType degrees) noexcept     { return degrees * (MathConstants<FloatType>::pi / FloatType (180)); }
417 
418 /** Converts an angle in radians to degrees. */
419 template <typename FloatType>
radiansToDegrees(FloatType radians)420 JUCE_CONSTEXPR FloatType radiansToDegrees (FloatType radians) noexcept     { return radians * (FloatType (180) / MathConstants<FloatType>::pi); }
421 
422 
423 //==============================================================================
424 /** The isfinite() method seems to vary between platforms, so this is a
425     platform-independent function for it.
426 */
427 template <typename NumericType>
juce_isfinite(NumericType)428 bool juce_isfinite (NumericType) noexcept
429 {
430     return true; // Integer types are always finite
431 }
432 
433 template <>
juce_isfinite(float value)434 inline bool juce_isfinite (float value) noexcept
435 {
436    #if JUCE_WINDOWS && ! JUCE_MINGW
437     return _finite (value) != 0;
438    #else
439     return std::isfinite (value);
440    #endif
441 }
442 
443 template <>
juce_isfinite(double value)444 inline bool juce_isfinite (double value) noexcept
445 {
446    #if JUCE_WINDOWS && ! JUCE_MINGW
447     return _finite (value) != 0;
448    #else
449     return std::isfinite (value);
450    #endif
451 }
452 
453 //==============================================================================
454 #if JUCE_MSVC
455  #pragma optimize ("t", off)
456  #ifndef __INTEL_COMPILER
457   #pragma float_control (precise, on, push)
458  #endif
459 #endif
460 
461 /** Fast floating-point-to-integer conversion.
462 
463     This is faster than using the normal c++ cast to convert a float to an int, and
464     it will round the value to the nearest integer, rather than rounding it down
465     like the normal cast does.
466 
467     Note that this routine gets its speed at the expense of some accuracy, and when
468     rounding values whose floating point component is exactly 0.5, odd numbers and
469     even numbers will be rounded up or down differently.
470 */
471 template <typename FloatType>
roundToInt(const FloatType value)472 int roundToInt (const FloatType value) noexcept
473 {
474   #ifdef __INTEL_COMPILER
475    #pragma float_control (precise, on, push)
476   #endif
477 
478     union { int asInt[2]; double asDouble; } n;
479     n.asDouble = ((double) value) + 6755399441055744.0;
480 
481    #if JUCE_BIG_ENDIAN
482     return n.asInt [1];
483    #else
484     return n.asInt [0];
485    #endif
486 }
487 
roundToInt(int value)488 inline int roundToInt (int value) noexcept
489 {
490     return value;
491 }
492 
493 #if JUCE_MSVC
494  #ifndef __INTEL_COMPILER
495   #pragma float_control (pop)
496  #endif
497  #pragma optimize ("", on)  // resets optimisations to the project defaults
498 #endif
499 
500 /** Fast floating-point-to-integer conversion.
501 
502     This is a slightly slower and slightly more accurate version of roundToInt(). It works
503     fine for values above zero, but negative numbers are rounded the wrong way.
504 */
roundToIntAccurate(double value)505 inline int roundToIntAccurate (double value) noexcept
506 {
507    #ifdef __INTEL_COMPILER
508     #pragma float_control (pop)
509    #endif
510 
511     return roundToInt (value + 1.5e-8);
512 }
513 
514 //==============================================================================
515 /** Truncates a positive floating-point number to an unsigned int.
516 
517     This is generally faster than static_cast<unsigned int> (std::floor (x))
518     but it only works for positive numbers small enough to be represented as an
519     unsigned int.
520 */
521 template <typename FloatType>
truncatePositiveToUnsignedInt(FloatType value)522 unsigned int truncatePositiveToUnsignedInt (FloatType value) noexcept
523 {
524     jassert (value >= static_cast<FloatType> (0));
525     jassert (static_cast<FloatType> (value) <= std::numeric_limits<unsigned int>::max());
526 
527     return static_cast<unsigned int> (value);
528 }
529 
530 //==============================================================================
531 /** Returns true if the specified integer is a power-of-two. */
532 template <typename IntegerType>
isPowerOfTwo(IntegerType value)533 JUCE_CONSTEXPR bool isPowerOfTwo (IntegerType value)
534 {
535    return (value & (value - 1)) == 0;
536 }
537 
538 /** Returns the smallest power-of-two which is equal to or greater than the given integer. */
nextPowerOfTwo(int n)539 inline int nextPowerOfTwo (int n) noexcept
540 {
541     --n;
542     n |= (n >> 1);
543     n |= (n >> 2);
544     n |= (n >> 4);
545     n |= (n >> 8);
546     n |= (n >> 16);
547     return n + 1;
548 }
549 
550 /** Returns the index of the highest set bit in a (non-zero) number.
551     So for n=3 this would return 1, for n=7 it returns 2, etc.
552     An input value of 0 is illegal!
553 */
554 int findHighestSetBit (uint32 n) noexcept;
555 
556 /** Returns the number of bits in a 32-bit integer. */
countNumberOfBits(uint32 n)557 inline int countNumberOfBits (uint32 n) noexcept
558 {
559     n -= ((n >> 1) & 0x55555555);
560     n =  (((n >> 2) & 0x33333333) + (n & 0x33333333));
561     n =  (((n >> 4) + n) & 0x0f0f0f0f);
562     n += (n >> 8);
563     n += (n >> 16);
564     return (int) (n & 0x3f);
565 }
566 
567 /** Returns the number of bits in a 64-bit integer. */
countNumberOfBits(uint64 n)568 inline int countNumberOfBits (uint64 n) noexcept
569 {
570     return countNumberOfBits ((uint32) n) + countNumberOfBits ((uint32) (n >> 32));
571 }
572 
573 /** Performs a modulo operation, but can cope with the dividend being negative.
574     The divisor must be greater than zero.
575 */
576 template <typename IntegerType>
negativeAwareModulo(IntegerType dividend,const IntegerType divisor)577 IntegerType negativeAwareModulo (IntegerType dividend, const IntegerType divisor) noexcept
578 {
579     jassert (divisor > 0);
580     dividend %= divisor;
581     return (dividend < 0) ? (dividend + divisor) : dividend;
582 }
583 
584 /** Returns the square of its argument. */
585 template <typename NumericType>
square(NumericType n)586 inline JUCE_CONSTEXPR NumericType square (NumericType n) noexcept
587 {
588     return n * n;
589 }
590 
591 //==============================================================================
592 /** Writes a number of bits into a memory buffer at a given bit index.
593     The buffer is treated as a sequence of 8-bit bytes, and the value is encoded in little-endian order,
594     so for example if startBit = 10, and numBits = 11 then the lower 6 bits of the value would be written
595     into bits 2-8 of targetBuffer[1], and the upper 5 bits of value into bits 0-5 of targetBuffer[2].
596 
597     @see readLittleEndianBitsInBuffer
598 */
599 void writeLittleEndianBitsInBuffer (void* targetBuffer, uint32 startBit, uint32 numBits, uint32 value) noexcept;
600 
601 /** Reads a number of bits from a buffer at a given bit index.
602     The buffer is treated as a sequence of 8-bit bytes, and the value is encoded in little-endian order,
603     so for example if startBit = 10, and numBits = 11 then the lower 6 bits of the result would be read
604     from bits 2-8 of sourceBuffer[1], and the upper 5 bits of the result from bits 0-5 of sourceBuffer[2].
605 
606     @see writeLittleEndianBitsInBuffer
607 */
608 uint32 readLittleEndianBitsInBuffer (const void* sourceBuffer, uint32 startBit, uint32 numBits) noexcept;
609 
610 
611 //==============================================================================
612 #if JUCE_INTEL || defined (DOXYGEN)
613  /** This macro can be applied to a float variable to check whether it contains a denormalised
614      value, and to normalise it if necessary.
615      On CPUs that aren't vulnerable to denormalisation problems, this will have no effect.
616  */
617  #define JUCE_UNDENORMALISE(x)   { (x) += 0.1f; (x) -= 0.1f; }
618 #else
619  #define JUCE_UNDENORMALISE(x)
620 #endif
621 
622 //==============================================================================
623 /** This namespace contains a few template classes for helping work out class type variations.
624 */
625 namespace TypeHelpers
626 {
627     /** The ParameterType struct is used to find the best type to use when passing some kind
628         of object as a parameter.
629 
630         Of course, this is only likely to be useful in certain esoteric template situations.
631 
632         E.g. "myFunction (typename TypeHelpers::ParameterType<int>::type, typename TypeHelpers::ParameterType<MyObject>::type)"
633         would evaluate to "myfunction (int, const MyObject&)", keeping any primitive types as
634         pass-by-value, but passing objects as a const reference, to avoid copying.
635 
636         @tags{Core}
637     */
638     template <typename Type> struct ParameterType                   { using type = const Type&; };
639 
640    #if ! DOXYGEN
641     template <typename Type> struct ParameterType <Type&>           { using type = Type&; };
642     template <typename Type> struct ParameterType <Type*>           { using type = Type*; };
643     template <>              struct ParameterType <char>            { using type = char; };
644     template <>              struct ParameterType <unsigned char>   { using type = unsigned char; };
645     template <>              struct ParameterType <short>           { using type = short; };
646     template <>              struct ParameterType <unsigned short>  { using type = unsigned short; };
647     template <>              struct ParameterType <int>             { using type = int; };
648     template <>              struct ParameterType <unsigned int>    { using type = unsigned int; };
649     template <>              struct ParameterType <long>            { using type = long; };
650     template <>              struct ParameterType <unsigned long>   { using type = unsigned long; };
651     template <>              struct ParameterType <int64>           { using type = int64; };
652     template <>              struct ParameterType <uint64>          { using type = uint64; };
653     template <>              struct ParameterType <bool>            { using type = bool; };
654     template <>              struct ParameterType <float>           { using type = float; };
655     template <>              struct ParameterType <double>          { using type = double; };
656    #endif
657 
658     /** These templates are designed to take a type, and if it's a double, they return a double
659         type; for anything else, they return a float type.
660 
661         @tags{Core}
662     */
663     template <typename Type> struct SmallestFloatType               { using type = float; };
664 
665    #if ! DOXYGEN
666     template <>              struct SmallestFloatType <double>      { using type = double; };
667    #endif
668 
669     /** These templates are designed to take an integer type, and return an unsigned int
670         version with the same size.
671 
672         @tags{Core}
673     */
674     template <int bytes>     struct UnsignedTypeWithSize            {};
675 
676    #if ! DOXYGEN
677     template <>              struct UnsignedTypeWithSize<1>         { using type = uint8; };
678     template <>              struct UnsignedTypeWithSize<2>         { using type = uint16; };
679     template <>              struct UnsignedTypeWithSize<4>         { using type = uint32; };
680     template <>              struct UnsignedTypeWithSize<8>         { using type = uint64; };
681    #endif
682 }
683 
684 //==============================================================================
685 #if ! DOXYGEN
686  // These old functions are deprecated: Just use roundToInt instead.
687  JUCE_DEPRECATED_ATTRIBUTE inline int roundDoubleToInt (double value) noexcept  { return roundToInt (value); }
688  JUCE_DEPRECATED_ATTRIBUTE inline int roundFloatToInt  (float  value) noexcept  { return roundToInt (value); }
689 
690  // This old function isn't needed - just use std::abs() instead
691  JUCE_DEPRECATED_ATTRIBUTE inline int64 abs64 (int64 n) noexcept                { return std::abs (n); }
692 #endif
693 
694 } // namespace juce
695