NUM.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #pragma once
  2. /* NUM.h
  3. *
  4. * Copyright (C) 2017,2018 Paul Boersma
  5. *
  6. * This code is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or (at
  9. * your option) any later version.
  10. *
  11. * This code is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. * See the GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. /*
  20. The following functions are called in inline functions,
  21. so they have to be declared first.
  22. */
  23. extern double NUMinner_ (const constVEC& x, const constVEC& y) noexcept;
  24. extern void NUM_sum_mean (const constVEC& x, double *out_sum, double *out_mean) noexcept;
  25. extern void NUM_sum_mean_sumsq_variance_stdev (const constVEC& x,
  26. double *out_sum, double *out_mean,
  27. double *out_sumsq, double *out_variance, double *out_stdev) noexcept;
  28. extern void NUM_sum_mean_sumsq_variance_stdev (const constMAT& x, integer columnNumber,
  29. double *out_sum, double *out_mean,
  30. double *out_sumsq, double *out_variance, double *out_stdev) noexcept;
  31. inline double NUMsum (constVEC x) noexcept {
  32. integer n = x.size;
  33. if (n <= 8) {
  34. if (n <= 2) return n <= 0 ? 0.0 : n == 1 ? x [1] : x [1] + x [2];
  35. if (n <= 4) return n == 3 ?
  36. (double) ((longdouble) x [1] + (longdouble) x [2] + (longdouble) x [3]) :
  37. (double) (((longdouble) x [1] + (longdouble) x [2]) + ((longdouble) x [3] + (longdouble) x [4]));
  38. if (n <= 6) return n == 5 ?
  39. (double) (((longdouble) x [1] + (longdouble) x [2] + (longdouble) x [3]) + ((longdouble) x [4] + (longdouble) x [5])) :
  40. (double) (((longdouble) x [1] + (longdouble) x [2] + (longdouble) x [3]) + ((longdouble) x [4] + (longdouble) x [5] + (longdouble) x [6]));
  41. return n == 7 ?
  42. (double) ((((longdouble) x [1] + (longdouble) x [2]) + ((longdouble) x [3] + (longdouble) x [4])) + ((longdouble) x [5] + (longdouble) x [6] + (longdouble) x [7])) :
  43. (double) ((((longdouble) x [1] + (longdouble) x [2]) + ((longdouble) x [3] + (longdouble) x [4])) + (((longdouble) x [5] + (longdouble) x [6]) + ((longdouble) x [7] + (longdouble) x [8])));
  44. }
  45. double sum;
  46. NUM_sum_mean (x, & sum, nullptr);
  47. return sum;
  48. }
  49. /*
  50. From here on, the functions appear in alphabetical order.
  51. */
  52. extern double NUMcenterOfGravity (const constVEC& x) noexcept;
  53. extern double NUMcolumnMean (const constMAT& x, integer columnNumber) noexcept;
  54. extern double NUMcolumnSum (const constMAT& x, integer columnNumber) noexcept;
  55. inline bool NUMdefined (const constMAT& x) noexcept {
  56. for (integer irow = 1; irow <= x.nrow; irow ++)
  57. for (integer icol = 1; icol <= x.ncol; icol ++)
  58. if (isundef (x [irow] [icol]))
  59. return false;
  60. return true;
  61. }
  62. template <typename T>
  63. bool NUMequal (const constvector<T>& x, const constvector<T>& y) noexcept {
  64. integer n = x.size;
  65. if (y.size != n)
  66. return false;
  67. for (integer i = 1; i <= n; i ++) {
  68. if (x [i] != y [i])
  69. return false;
  70. }
  71. return true;
  72. }
  73. template <typename T>
  74. bool NUMequal (const vector<T>& x, const constvector<T>& y) noexcept {
  75. return NUMequal (constvector<T> (x), y);
  76. }
  77. template <typename T>
  78. bool NUMequal (const constvector<T>& x, const vector<T>& y) noexcept {
  79. return NUMequal (x, constvector<T> (y));
  80. }
  81. template <typename T>
  82. bool NUMequal (const vector<T>& x, const vector<T>& y) noexcept {
  83. return NUMequal (constvector<T> (x), constvector<T> (y));
  84. }
  85. template <typename T>
  86. bool NUMequal (const constmatrix<T>& x, const constmatrix<T>& y) noexcept {
  87. return NUMequal (asvector (x), asvector (y));
  88. }
  89. template <typename T>
  90. bool NUMequal (const matrix<T>& x, const constmatrix<T>& y) noexcept {
  91. return NUMequal (constmatrix<T> (x), y);
  92. }
  93. template <typename T>
  94. bool NUMequal (const constmatrix<T>& x, const matrix<T>& y) noexcept {
  95. return NUMequal (x, constmatrix<T> (y));
  96. }
  97. template <typename T>
  98. bool NUMequal (const matrix<T>& x, const matrix<T>& y) noexcept {
  99. return NUMequal (constmatrix<T> (x), constmatrix<T> (y));
  100. }
  101. inline bool NUMequal (constSTRVEC x, constSTRVEC y) noexcept {
  102. integer n = x.size;
  103. if (y.size != n)
  104. return false;
  105. for (integer i = 1; i <= n; i ++) {
  106. if (! Melder_equ (x [i], y [i]))
  107. return false;
  108. }
  109. return true;
  110. }
  111. inline double NUMextremum (const constVEC& vec) noexcept {
  112. double extremum = 0.0;
  113. for (integer i = 1; i <= vec.size; i ++)
  114. if (fabs (vec [i]) > extremum) extremum = fabs (vec [i]);
  115. return extremum;
  116. }
  117. inline double NUMextremum (const constMAT& mat) noexcept {
  118. return NUMextremum (asvector (mat));
  119. }
  120. inline double NUMinner (const constVEC& x, const constVEC& y) noexcept {
  121. integer n = x.size;
  122. Melder_assert (y.size == n);
  123. if (n <= 8) {
  124. if (n <= 2) return n <= 0 ? 0.0 : n == 1 ? x [1] * y [1] : (double) ((longdouble) x [1] * (longdouble) y [1] + (longdouble) x [2] * (longdouble) y [2]);
  125. if (n <= 4) return n == 3 ?
  126. (double) ((longdouble) x [1] * (longdouble) y [1] + (longdouble) x [2] * (longdouble) y [2] + (longdouble) x [3] * (longdouble) y [3]) :
  127. (double) (((longdouble) x [1] * (longdouble) y [1] + (longdouble) x [2] * (longdouble) y [2]) + ((longdouble) x [3] * (longdouble) y [3] + (longdouble) x [4] * (longdouble) y [4]));
  128. if (n <= 6) return n == 5 ?
  129. (double) (((longdouble) x [1] * (longdouble) y [1] + (longdouble) x [2] * (longdouble) y [2] + (longdouble) x [3] * (longdouble) y [3]) + ((longdouble) x [4] * (longdouble) y [4] + (longdouble) x [5] * (longdouble) y [5])) :
  130. (double) (((longdouble) x [1] * (longdouble) y [1] + (longdouble) x [2] * (longdouble) y [2] + (longdouble) x [3] * (longdouble) y [3]) + ((longdouble) x [4] * (longdouble) y [4] + (longdouble) x [5] * (longdouble) y [5] + (longdouble) x [6] * (longdouble) y [6]));
  131. return n == 7 ?
  132. (double) ((((longdouble) x [1] * (longdouble) y [1] + (longdouble) x [2] * (longdouble) y [2]) + ((longdouble) x [3] * (longdouble) y [3] + (longdouble) x [4] * (longdouble) y [4])) + ((longdouble) x [5] * (longdouble) y [5] + (longdouble) x [6] * (longdouble) y [6] + (longdouble) x [7] * (longdouble) y [7])) :
  133. (double) ((((longdouble) x [1] * (longdouble) y [1] + (longdouble) x [2] * (longdouble) y [2]) + ((longdouble) x [3] * (longdouble) y [3] + (longdouble) x [4] * (longdouble) y [4])) + (((longdouble) x [5] * (longdouble) y [5] + (longdouble) x [6] * (longdouble) y [6]) + ((longdouble) x [7] * (longdouble) y [7] + (longdouble) x [8] * (longdouble) y [8])));
  134. }
  135. return NUMinner_ (x, y);
  136. }
  137. inline bool NUMisEmpty (const constVEC& x) noexcept {
  138. return x.size == 0; // note: testing on x.at is incorrect, because the capacity may be large when the size is 0
  139. }
  140. inline bool NUMisEmpty (const constMAT& x) noexcept {
  141. integer numberOfCells = x.nrow * x.ncol;
  142. return numberOfCells == 0; // note: a matrix with 0 rows and 6 columns is a valid empty matrix, to which e.g. a row can be added
  143. }
  144. inline bool NUMisSymmetric (const constMAT& x) noexcept {
  145. if (x.nrow != x.ncol) return false;
  146. integer n = x.nrow;
  147. for (integer irow = 1; irow <= n; irow ++)
  148. for (integer icol = irow + 1; icol < n; icol ++)
  149. if (x [irow] [icol] != x [icol] [irow])
  150. return false;
  151. return true;
  152. }
  153. inline integer NUMlength (conststring32 str) {
  154. return str ? str32len (str) : 0;
  155. }
  156. inline double NUMlog2 (double x) {
  157. return log (x) * NUMlog2e;
  158. }
  159. inline double NUMmean (const constVEC& x) noexcept {
  160. integer n = x.size;
  161. if (n <= 8) {
  162. if (n <= 2) return n <= 0 ? undefined : n == 1 ? x [1] : (double) (0.5 * ((longdouble) x [1] + (longdouble) x [2]));
  163. if (n <= 4) return n == 3 ?
  164. (double) ((1.0 / (longdouble) 3.0) * ((longdouble) x [1] + (longdouble) x [2] + (longdouble) x [3])) :
  165. (double) (0.25 * (((longdouble) x [1] + (longdouble) x [2]) + ((longdouble) x [3] + (longdouble) x [4])));
  166. if (n <= 6) return n == 5 ?
  167. (double) ((1.0 / (longdouble) 5.0) * (((longdouble) x [1] + (longdouble) x [2] + (longdouble) x [3]) + ((longdouble) x [4] + (longdouble) x [5]))) :
  168. (double) ((1.0 / (longdouble) 6.0) * (((longdouble) x [1] + (longdouble) x [2] + (longdouble) x [3]) + ((longdouble) x [4] + (longdouble) x [5] + (longdouble) x [6])));
  169. return n == 7 ?
  170. (double) ((1.0 / (longdouble) 7.0) * ((((longdouble) x [1] + (longdouble) x [2]) + ((longdouble) x [3] + (longdouble) x [4])) + ((longdouble) x [5] + (longdouble) x [6] + (longdouble) x [7]))) :
  171. (double) (0.125 * ((((longdouble) x [1] + (longdouble) x [2]) + ((longdouble) x [3] + (longdouble) x [4])) + (((longdouble) x [5] + (longdouble) x [6]) + ((longdouble) x [7] + (longdouble) x [8]))));
  172. }
  173. double mean;
  174. NUM_sum_mean (x, nullptr, & mean);
  175. return mean;
  176. }
  177. double NUMnorm (const constVEC& x, double power) noexcept;
  178. inline double NUMnorm (const constMAT& x, double power) noexcept {
  179. return NUMnorm (asvector (x), power);
  180. }
  181. integer NUMnumberOfTokens (conststring32 str) noexcept;
  182. /*
  183. Return zero for non-positive base.
  184. */
  185. inline double NUMpow (double base, double exponent) {
  186. return base <= 0.0 ? 0.0 : pow (base, exponent);
  187. }
  188. inline double NUMrowSum (const constMAT& x, integer rowNumber) noexcept {
  189. Melder_assert (rowNumber > 0 && rowNumber <= x.nrow);
  190. return NUMsum (constVEC (x [rowNumber], x.ncol));
  191. }
  192. inline double NUMsqrt (double x) {
  193. #if defined (_WIN32)
  194. if (x < 0.0) return undefined;
  195. #endif
  196. return sqrt (x);
  197. }
  198. extern double NUMstdev (const constVEC& x) noexcept;
  199. inline double NUMsum (const constMAT& x) noexcept {
  200. return NUMsum (asvector (x));
  201. }
  202. extern double NUMsumsq (const constVEC& x) noexcept;
  203. extern double NUMvariance (const constVEC& x) noexcept;
  204. /* End of file NUM.h */