OpenShot Audio Library | OpenShotAudio  0.3.1
juce_MathsFunctions.h
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 
35 using int8 = signed char;
37 using uint8 = unsigned char;
39 using int16 = signed short;
41 using uint16 = unsigned short;
43 using int32 = signed int;
45 using uint32 = unsigned int;
46 
47 #if JUCE_MSVC
49  using int64 = __int64;
51  using uint64 = unsigned __int64;
52 #else
54  using int64 = long long;
56  using uint64 = unsigned long long;
57 #endif
58 
59 #ifndef DOXYGEN
65  #define literal64bit(longLiteral) (longLiteral##LL)
66 #endif
67 
68 #if JUCE_64BIT
70  using pointer_sized_int = int64;
72  using pointer_sized_uint = uint64;
73 #elif JUCE_MSVC
75  using pointer_sized_int = _W64 int;
77  using pointer_sized_uint = _W64 unsigned int;
78 #else
80  using pointer_sized_int = int;
82  using pointer_sized_uint = unsigned int;
83 #endif
84 
85 #if JUCE_WINDOWS && ! JUCE_MINGW
86  using ssize_t = pointer_sized_int;
87 #endif
88 
89 //==============================================================================
90 // Some indispensable min/max functions
91 
93 template <typename Type>
94 JUCE_CONSTEXPR Type jmax (Type a, Type b) { return a < b ? b : a; }
95 
97 template <typename Type>
98 JUCE_CONSTEXPR Type jmax (Type a, Type b, Type c) { return a < b ? (b < c ? c : b) : (a < c ? c : a); }
99 
101 template <typename Type>
102 JUCE_CONSTEXPR Type jmax (Type a, Type b, Type c, Type d) { return jmax (a, jmax (b, c, d)); }
103 
105 template <typename Type>
106 JUCE_CONSTEXPR Type jmin (Type a, Type b) { return b < a ? b : a; }
107 
109 template <typename Type>
110 JUCE_CONSTEXPR Type jmin (Type a, Type b, Type c) { return b < a ? (c < b ? c : b) : (c < a ? c : a); }
111 
113 template <typename Type>
114 JUCE_CONSTEXPR Type jmin (Type a, Type b, Type c, Type d) { return jmin (a, jmin (b, c, d)); }
115 
119 template <typename Type>
120 JUCE_CONSTEXPR Type jmap (Type value0To1, Type targetRangeMin, Type targetRangeMax)
121 {
122  return targetRangeMin + value0To1 * (targetRangeMax - targetRangeMin);
123 }
124 
126 template <typename Type>
127 Type jmap (Type sourceValue, Type sourceRangeMin, Type sourceRangeMax, Type targetRangeMin, Type targetRangeMax)
128 {
129  jassert (sourceRangeMax != sourceRangeMin); // mapping from a range of zero will produce NaN!
130  return targetRangeMin + ((targetRangeMax - targetRangeMin) * (sourceValue - sourceRangeMin)) / (sourceRangeMax - sourceRangeMin);
131 }
132 
134 template <typename Type>
135 Type findMinimum (const Type* data, int numValues)
136 {
137  if (numValues <= 0)
138  return Type (0);
139 
140  auto result = *data++;
141 
142  while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
143  {
144  auto v = *data++;
145 
146  if (v < result)
147  result = v;
148  }
149 
150  return result;
151 }
152 
154 template <typename Type>
155 Type findMaximum (const Type* values, int numValues)
156 {
157  if (numValues <= 0)
158  return Type (0);
159 
160  auto result = *values++;
161 
162  while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
163  {
164  auto v = *values++;
165 
166  if (result < v)
167  result = v;
168  }
169 
170  return result;
171 }
172 
174 template <typename Type>
175 void findMinAndMax (const Type* values, int numValues, Type& lowest, Type& highest)
176 {
177  if (numValues <= 0)
178  {
179  lowest = Type (0);
180  highest = Type (0);
181  }
182  else
183  {
184  auto mn = *values++;
185  auto mx = mn;
186 
187  while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
188  {
189  auto v = *values++;
190 
191  if (mx < v) mx = v;
192  if (v < mn) mn = v;
193  }
194 
195  lowest = mn;
196  highest = mx;
197  }
198 }
199 
200 //==============================================================================
217 template <typename Type>
218 Type jlimit (Type lowerLimit,
219  Type upperLimit,
220  Type valueToConstrain) noexcept
221 {
222  jassert (lowerLimit <= upperLimit); // if these are in the wrong order, results are unpredictable..
223 
224  return valueToConstrain < lowerLimit ? lowerLimit
225  : (upperLimit < valueToConstrain ? upperLimit
226  : valueToConstrain);
227 }
228 
234 template <typename Type1, typename Type2>
235 bool isPositiveAndBelow (Type1 valueToTest, Type2 upperLimit) noexcept
236 {
237  jassert (Type1() <= static_cast<Type1> (upperLimit)); // makes no sense to call this if the upper limit is itself below zero..
238  return Type1() <= valueToTest && valueToTest < static_cast<Type1> (upperLimit);
239 }
240 
241 template <typename Type>
242 bool isPositiveAndBelow (int valueToTest, Type upperLimit) noexcept
243 {
244  jassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero..
245  return static_cast<unsigned int> (valueToTest) < static_cast<unsigned int> (upperLimit);
246 }
247 
253 template <typename Type1, typename Type2>
254 bool isPositiveAndNotGreaterThan (Type1 valueToTest, Type2 upperLimit) noexcept
255 {
256  jassert (Type1() <= static_cast<Type1> (upperLimit)); // makes no sense to call this if the upper limit is itself below zero..
257  return Type1() <= valueToTest && valueToTest <= static_cast<Type1> (upperLimit);
258 }
259 
260 template <typename Type>
261 bool isPositiveAndNotGreaterThan (int valueToTest, Type upperLimit) noexcept
262 {
263  jassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero..
264  return static_cast<unsigned int> (valueToTest) <= static_cast<unsigned int> (upperLimit);
265 }
266 
270 template <typename Type>
271 bool isWithin (Type a, Type b, Type tolerance) noexcept
272 {
273  return std::abs (a - b) <= tolerance;
274 }
275 
279 template <typename Type>
280 bool approximatelyEqual (Type a, Type b) noexcept
281 {
282  return std::abs (a - b) <= (std::numeric_limits<Type>::epsilon() * std::max (a, b))
283  || std::abs (a - b) < std::numeric_limits<Type>::min();
284 }
285 
286 //==============================================================================
288 template <typename... Types>
289 void ignoreUnused (Types&&...) noexcept {}
290 
299 template <typename Type, size_t N>
300 JUCE_CONSTEXPR int numElementsInArray (Type (&)[N]) noexcept { return N; }
301 
302 //==============================================================================
303 // Some useful maths functions that aren't always present with all compilers and build settings.
304 
307 template <typename Type>
308 Type juce_hypot (Type a, Type b) noexcept
309 {
310  #if JUCE_MSVC
311  return static_cast<Type> (_hypot (a, b));
312  #else
313  return static_cast<Type> (hypot (a, b));
314  #endif
315 }
316 
317 #ifndef DOXYGEN
318 template <>
319 inline float juce_hypot (float a, float b) noexcept
320 {
321  #if JUCE_MSVC
322  return _hypotf (a, b);
323  #else
324  return hypotf (a, b);
325  #endif
326 }
327 #endif
328 
329 //==============================================================================
330 #if JUCE_HAS_CONSTEXPR
331 
336 template <typename FloatType>
337 struct MathConstants
338 {
340  static constexpr FloatType pi = static_cast<FloatType> (3.141592653589793238L);
341 
343  static constexpr FloatType twoPi = static_cast<FloatType> (2 * 3.141592653589793238L);
344 
346  static constexpr FloatType halfPi = static_cast<FloatType> (3.141592653589793238L / 2);
347 
349  static constexpr FloatType euler = static_cast<FloatType> (2.71828182845904523536L);
350 
352  static constexpr FloatType sqrt2 = static_cast<FloatType> (1.4142135623730950488L);
353 };
354 
355 #else
356 
361 template <typename FloatType>
363 {
365  static const FloatType pi;
366 
368  static const FloatType twoPi;
369 
371  static const FloatType halfPi;
372 
374  static const FloatType euler;
375 
377  static const FloatType sqrt2;
378 };
379 
380 template <typename FloatType>
381 const FloatType MathConstants<FloatType>::pi = static_cast<FloatType> (3.141592653589793238L);
382 
383 template <typename FloatType>
384 const FloatType MathConstants<FloatType>::twoPi = static_cast<FloatType> (2 * 3.141592653589793238L);
385 
386 template <typename FloatType>
387 const FloatType MathConstants<FloatType>::halfPi = static_cast<FloatType> (3.141592653589793238L / 2);
388 
389 template <typename FloatType>
390 const FloatType MathConstants<FloatType>::euler = static_cast<FloatType> (2.71828182845904523536L);
391 
392 template <typename FloatType>
393 const FloatType MathConstants<FloatType>::sqrt2 = static_cast<FloatType> (1.4142135623730950488L);
394 
395 #endif
396 
397 #ifndef DOXYGEN
403 const JUCE_CONSTEXPR double double_Pi = MathConstants<double>::pi;
404 
410 const JUCE_CONSTEXPR float float_Pi = MathConstants<float>::pi;
411 #endif
412 
414 template <typename FloatType>
415 JUCE_CONSTEXPR FloatType degreesToRadians (FloatType degrees) noexcept { return degrees * (MathConstants<FloatType>::pi / FloatType (180)); }
416 
418 template <typename FloatType>
419 JUCE_CONSTEXPR FloatType radiansToDegrees (FloatType radians) noexcept { return radians * (FloatType (180) / MathConstants<FloatType>::pi); }
420 
421 
422 //==============================================================================
426 template <typename NumericType>
427 bool juce_isfinite (NumericType) noexcept
428 {
429  return true; // Integer types are always finite
430 }
431 
432 template <>
433 inline bool juce_isfinite (float value) noexcept
434 {
435  #if JUCE_WINDOWS && ! JUCE_MINGW
436  return _finite (value) != 0;
437  #else
438  return std::isfinite (value);
439  #endif
440 }
441 
442 template <>
443 inline bool juce_isfinite (double value) noexcept
444 {
445  #if JUCE_WINDOWS && ! JUCE_MINGW
446  return _finite (value) != 0;
447  #else
448  return std::isfinite (value);
449  #endif
450 }
451 
452 //==============================================================================
453 #if JUCE_MSVC
454  #pragma optimize ("t", off)
455  #ifndef __INTEL_COMPILER
456  #pragma float_control (precise, on, push)
457  #endif
458 #endif
459 
470 template <typename FloatType>
471 int roundToInt (const FloatType value) noexcept
472 {
473  #ifdef __INTEL_COMPILER
474  #pragma float_control (precise, on, push)
475  #endif
476 
477  union { int asInt[2]; double asDouble; } n;
478  n.asDouble = ((double) value) + 6755399441055744.0;
479 
480  #if JUCE_BIG_ENDIAN
481  return n.asInt [1];
482  #else
483  return n.asInt [0];
484  #endif
485 }
486 
487 inline int roundToInt (int value) noexcept
488 {
489  return value;
490 }
491 
492 #if JUCE_MSVC
493  #ifndef __INTEL_COMPILER
494  #pragma float_control (pop)
495  #endif
496  #pragma optimize ("", on) // resets optimisations to the project defaults
497 #endif
498 
504 inline int roundToIntAccurate (double value) noexcept
505 {
506  #ifdef __INTEL_COMPILER
507  #pragma float_control (pop)
508  #endif
509 
510  return roundToInt (value + 1.5e-8);
511 }
512 
513 //==============================================================================
520 template <typename FloatType>
521 unsigned int truncatePositiveToUnsignedInt (FloatType value) noexcept
522 {
523  jassert (value >= static_cast<FloatType> (0));
524  jassert (static_cast<FloatType> (value) <= std::numeric_limits<unsigned int>::max());
525 
526  return static_cast<unsigned int> (value);
527 }
528 
529 //==============================================================================
531 template <typename IntegerType>
532 JUCE_CONSTEXPR bool isPowerOfTwo (IntegerType value)
533 {
534  return (value & (value - 1)) == 0;
535 }
536 
538 inline int nextPowerOfTwo (int n) noexcept
539 {
540  --n;
541  n |= (n >> 1);
542  n |= (n >> 2);
543  n |= (n >> 4);
544  n |= (n >> 8);
545  n |= (n >> 16);
546  return n + 1;
547 }
548 
553 int findHighestSetBit (uint32 n) noexcept;
554 
556 inline int countNumberOfBits (uint32 n) noexcept
557 {
558  n -= ((n >> 1) & 0x55555555);
559  n = (((n >> 2) & 0x33333333) + (n & 0x33333333));
560  n = (((n >> 4) + n) & 0x0f0f0f0f);
561  n += (n >> 8);
562  n += (n >> 16);
563  return (int) (n & 0x3f);
564 }
565 
567 inline int countNumberOfBits (uint64 n) noexcept
568 {
569  return countNumberOfBits ((uint32) n) + countNumberOfBits ((uint32) (n >> 32));
570 }
571 
575 template <typename IntegerType>
576 IntegerType negativeAwareModulo (IntegerType dividend, const IntegerType divisor) noexcept
577 {
578  jassert (divisor > 0);
579  dividend %= divisor;
580  return (dividend < 0) ? (dividend + divisor) : dividend;
581 }
582 
584 template <typename NumericType>
585 inline JUCE_CONSTEXPR NumericType square (NumericType n) noexcept
586 {
587  return n * n;
588 }
589 
590 //==============================================================================
598 void writeLittleEndianBitsInBuffer (void* targetBuffer, uint32 startBit, uint32 numBits, uint32 value) noexcept;
599 
607 uint32 readLittleEndianBitsInBuffer (const void* sourceBuffer, uint32 startBit, uint32 numBits) noexcept;
608 
609 
610 //==============================================================================
611 #if JUCE_INTEL || defined (DOXYGEN)
616  #define JUCE_UNDENORMALISE(x) { (x) += 0.1f; (x) -= 0.1f; }
617 #else
618  #define JUCE_UNDENORMALISE(x)
619 #endif
620 
621 //==============================================================================
624 namespace TypeHelpers
625 {
637  template <typename Type> struct ParameterType { using type = const Type&; };
638 
639  #if ! DOXYGEN
640  template <typename Type> struct ParameterType <Type&> { using type = Type&; };
641  template <typename Type> struct ParameterType <Type*> { using type = Type*; };
642  template <> struct ParameterType <char> { using type = char; };
643  template <> struct ParameterType <unsigned char> { using type = unsigned char; };
644  template <> struct ParameterType <short> { using type = short; };
645  template <> struct ParameterType <unsigned short> { using type = unsigned short; };
646  template <> struct ParameterType <int> { using type = int; };
647  template <> struct ParameterType <unsigned int> { using type = unsigned int; };
648  template <> struct ParameterType <long> { using type = long; };
649  template <> struct ParameterType <unsigned long> { using type = unsigned long; };
650  template <> struct ParameterType <int64> { using type = int64; };
651  template <> struct ParameterType <uint64> { using type = uint64; };
652  template <> struct ParameterType <bool> { using type = bool; };
653  template <> struct ParameterType <float> { using type = float; };
654  template <> struct ParameterType <double> { using type = double; };
655  #endif
656 
662  template <typename Type> struct SmallestFloatType { using type = float; };
663 
664  #if ! DOXYGEN
665  template <> struct SmallestFloatType <double> { using type = double; };
666  #endif
667 
673  template <int bytes> struct UnsignedTypeWithSize {};
674 
675  #if ! DOXYGEN
676  template <> struct UnsignedTypeWithSize<1> { using type = uint8; };
677  template <> struct UnsignedTypeWithSize<2> { using type = uint16; };
678  template <> struct UnsignedTypeWithSize<4> { using type = uint32; };
679  template <> struct UnsignedTypeWithSize<8> { using type = uint64; };
680  #endif
681 }
682 
683 //==============================================================================
684 #if ! DOXYGEN
685  // These old functions are deprecated: Just use roundToInt instead.
686  JUCE_DEPRECATED_ATTRIBUTE inline int roundDoubleToInt (double value) noexcept { return roundToInt (value); }
687  JUCE_DEPRECATED_ATTRIBUTE inline int roundFloatToInt (float value) noexcept { return roundToInt (value); }
688 
689  // This old function isn't needed - just use std::abs() instead
690  JUCE_DEPRECATED_ATTRIBUTE inline int64 abs64 (int64 n) noexcept { return std::abs (n); }
691 #endif
692 
693 } // namespace juce
static const FloatType euler
static const FloatType twoPi
static const FloatType sqrt2
static const FloatType halfPi
static const FloatType pi