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