MAT.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. #pragma once
  2. /* MAT.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. Some functions that are included below.
  21. */
  22. /*
  23. From here on alphabetical order.
  24. */
  25. inline void MATadd_inplace (const MAT& x, double addend) noexcept {
  26. asvector (x) += addend;
  27. }
  28. inline const MAT& operator+= (const MAT& x, double addend) noexcept {
  29. asvector (x) += addend;
  30. return x;
  31. }
  32. inline void MATadd_inplace (const MAT& x, const constMAT& y) noexcept {
  33. ////VECadd_inplace (asvector (x), asvector (y));
  34. asvector (x) += asvector (y);
  35. }
  36. inline const MAT& operator+= (const MAT& x, const constMAT& y) noexcept {
  37. ////VECadd_inplace (asvector (x), asvector (y));
  38. asvector (x) += asvector (y);
  39. return x;
  40. }
  41. inline void MATadd_preallocated (const MAT& target, const constMAT& x, double addend) noexcept {
  42. Melder_assert (x.nrow == target.nrow && x.ncol == target.ncol);
  43. VECadd_preallocated (asvector (target), asvector (x), addend);
  44. }
  45. inline autoMAT MATadd (const constMAT& x, double addend) {
  46. autoMAT result = MATraw (x.nrow, x.ncol);
  47. MATadd_preallocated (result.get(), x, addend);
  48. return result;
  49. }
  50. inline void MATadd_preallocated (const MAT& target, const constMAT& x, const constMAT& y) noexcept {
  51. Melder_assert (x.nrow == target.nrow && x.ncol == target.ncol);
  52. Melder_assert (y.nrow == x.nrow && y.ncol == x.ncol);
  53. VECadd_preallocated (asvector (target), asvector (x), asvector (y));
  54. }
  55. inline autoMAT MATadd (const constMAT& x, const constMAT& y) noexcept {
  56. autoMAT result = MATraw (x.nrow, x.ncol);
  57. MATadd_preallocated (result.get(), x, y);
  58. return result;
  59. }
  60. /*
  61. Make the average of each column zero.
  62. a[i][j] -= a[.][j]
  63. */
  64. extern void MATcentreEachColumn_inplace (const MAT& x) noexcept;
  65. /*
  66. Make the average of each row zero.
  67. a[i][j] -= a[i][.]
  68. */
  69. extern void MATcentreEachRow_inplace (const MAT& x) noexcept;
  70. /*
  71. Make the average of every column and every row zero.
  72. a[i][j] += - a[i][.] - a[.][j] + a[.][.]
  73. */
  74. extern void MATdoubleCentre_inplace (const MAT& x) noexcept;
  75. extern void MATmtm_preallocated (const MAT& target, const constMAT& x) noexcept;
  76. inline autoMAT MATmtm (const constMAT& x) {
  77. autoMAT result = MATraw (x.ncol, x.ncol);
  78. MATmtm_preallocated (result.get(), x);
  79. return result;
  80. }
  81. /*
  82. Target := X . Y
  83. Precise matrix multiplication, using pairwise summation.
  84. The speed is 7,0.69,0.51,1.96 ns per multiply-add
  85. for x.nrow = x.ncol = y.nrow = y.ncol = 1,10,100,1000.
  86. For large matrices this is a bit slow.
  87. */
  88. extern void MATmul_preallocated_ (const MAT& target, const constMAT& x, const constMAT& y) noexcept;
  89. inline void MATmul_preallocated (const MAT& target, const constMAT& x, const constMAT& y) noexcept {
  90. Melder_assert (target.nrow == x.nrow);
  91. Melder_assert (target.ncol == y.ncol);
  92. Melder_assert (x.ncol == y.nrow);
  93. MATmul_preallocated_ (target, x, y);
  94. }
  95. inline autoMAT MATmul (const constMAT& x, const constMAT& y) {
  96. autoMAT result = MATraw (x.nrow, y.ncol);
  97. MATmul_preallocated (result.get(), x, y);
  98. return result;
  99. }
  100. /*
  101. Rough matrix multiplication, using an in-cache inner loop.
  102. The speed is 10,0.76,0.32,0.34 ns per multiply-add
  103. for x.nrow = x.ncol = y.nrow = y.ncol = 1,10,100,1000.
  104. */
  105. extern void MATmul_fast_preallocated_ (const MAT& target, const constMAT& x, const constMAT& y) noexcept;
  106. inline void MATmul_fast_preallocated (const MAT& target, const constMAT& x, const constMAT& y) noexcept {
  107. Melder_assert (target.nrow == x.nrow);
  108. Melder_assert (target.ncol == y.ncol);
  109. Melder_assert (x.ncol == y.nrow);
  110. MATmul_fast_preallocated_ (target, x, y);
  111. }
  112. inline autoMAT MATmul_fast (const constMAT& x, const constMAT& y) {
  113. autoMAT result = MATraw (x.nrow, y.ncol);
  114. MATmul_fast_preallocated (result.get(), x, y);
  115. return result;
  116. }
  117. /*
  118. Target := X . Y'
  119. Pairwise summation.
  120. The speed is 7,0.71,0.52,0.52 ns per multiply-add
  121. for x.nrow = x.ncol = y.nrow = y.col = 1,10,100,1000.
  122. */
  123. extern void MATmul_nt_preallocated_ (const MAT& target, const constMAT& x, const constMAT& y) noexcept;
  124. inline void MATmul_nt_preallocated (const MAT& target, const constMAT& x, const constMAT& y) noexcept {
  125. Melder_assert (target.nrow == x.nrow);
  126. Melder_assert (target.ncol == y.nrow);
  127. Melder_assert (x.ncol == y.ncol);
  128. MATmul_nt_preallocated_ (target, x, y);
  129. }
  130. inline autoMAT MATmul_nt (const constMAT& x, const constMAT& y) {
  131. autoMAT result = MATraw (x.nrow, y.nrow);
  132. MATmul_nt_preallocated (result.get(), x, y);
  133. return result;
  134. }
  135. /*
  136. Target := X' . Y
  137. Pairwise summation.
  138. The speed is 7,0.79,0.62,15.1 ns per multiply-add
  139. for x.nrow = x.ncol = y.nrow = y.col = 1,10,100,1000.
  140. For large matrices this is very slow.
  141. */
  142. extern void MATmul_tn_preallocated_ (const MAT& target, const constMAT& x, const constMAT& y) noexcept;
  143. inline void MATmul_tn_preallocated (const MAT& target, const constMAT& x, const constMAT& y) noexcept {
  144. Melder_assert (target.nrow == x.ncol);
  145. Melder_assert (target.ncol == y.ncol);
  146. Melder_assert (x.nrow == y.nrow);
  147. MATmul_tn_preallocated_ (target, x, y);
  148. }
  149. inline autoMAT MATmul_tn (const constMAT& x, const constMAT& y) {
  150. autoMAT result = MATraw (x.ncol, y.ncol);
  151. MATmul_tn_preallocated (result.get(), x, y);
  152. return result;
  153. }
  154. /*
  155. Rough matrix multiplication, using an in-cache inner loop.
  156. The speed is 11,0.79,0.32,0.37 ns per multiply-add
  157. for x.nrow = x.ncol = y.nrow = y.ncol = 1,10,100,1000.
  158. */
  159. extern void MATmul_tn_fast_preallocated_ (const MAT& target, const constMAT& x, const constMAT& y) noexcept;
  160. inline void MATmul_tn_fast_preallocated (const MAT& target, const constMAT& x, const constMAT& y) noexcept {
  161. Melder_assert (target.nrow == x.ncol);
  162. Melder_assert (target.ncol == y.ncol);
  163. Melder_assert (x.nrow == y.nrow);
  164. MATmul_tn_fast_preallocated (target, x, y);
  165. }
  166. inline autoMAT MATmul_tn_fast (const constMAT& x, const constMAT& y) {
  167. autoMAT result = MATraw (x.ncol, y.ncol);
  168. MATmul_tn_fast_preallocated (result.get(), x, y);
  169. return result;
  170. }
  171. /*
  172. Target := X' . Y'
  173. Pairwise summation.
  174. The speed is 7,0.66,0.47,1.49 ns per multiply-add
  175. for x.nrow = x.ncol = y.nrow = y.col = 1,10,100,1000.
  176. For large matrices this is a bit slow.
  177. */
  178. extern void MATmul_tt_preallocated_ (const MAT& target, const constMAT& x, const constMAT& y) noexcept;
  179. inline void MATmul_tt_preallocated (const MAT& target, const constMAT& x, const constMAT& y) noexcept {
  180. Melder_assert (target.nrow == x.ncol);
  181. Melder_assert (target.ncol == y.nrow);
  182. Melder_assert (x.nrow == y.ncol);
  183. MATmul_tt_preallocated_ (target, x, y);
  184. }
  185. inline autoMAT MATmul_tt (const constMAT& x, const constMAT& y) {
  186. autoMAT result = MATraw (x.ncol, y.nrow);
  187. MATmul_tt_preallocated (result.get(), x, y);
  188. return result;
  189. }
  190. /*
  191. Rough matrix multiplication.
  192. The speed is 9,0.51,0.70,1.36 ns per multiply-add
  193. for x.nrow = x.ncol = y.nrow = y.ncol = 1,10,100,1000.
  194. Not so fast for large matrices.
  195. */
  196. extern void MATmul_tt_fast_preallocated_ (const MAT& target, const constMAT& x, const constMAT& y) noexcept(false);
  197. inline void MATmul_tt_fast_preallocated (const MAT& target, const constMAT& x, const constMAT& y) noexcept(false) {
  198. Melder_assert (target.nrow == x.ncol);
  199. Melder_assert (target.ncol == y.nrow);
  200. Melder_assert (x.nrow == y.ncol);
  201. MATmul_tt_fast_preallocated_ (target, x, y);
  202. }
  203. inline autoMAT MATmul_tt_fast (const constMAT& x, const constMAT& y) {
  204. autoMAT result = MATraw (x.ncol, y.nrow);
  205. MATmul_tt_fast_preallocated (result.get(), x, y);
  206. return result;
  207. }
  208. inline void MATmultiply_inplace (const MAT& x, double factor) noexcept {
  209. for (integer irow = 1; irow <= x.nrow; irow ++)
  210. for (integer icol = 1; icol <= x.ncol; icol ++)
  211. x [irow] [icol] *= factor;
  212. }
  213. extern autoMAT MATouter (const constVEC& x, const constVEC& y);
  214. extern autoMAT MATpeaks (const constVEC& x, bool includeEdges, int interpolate, bool sortByHeight);
  215. inline autoMAT MATrandomGauss (integer nrow, integer ncol, double mu, double sigma) {
  216. autoMAT result = MATraw (nrow, ncol);
  217. for (integer irow = 1; irow <= nrow; irow ++)
  218. for (integer icol = 1; icol <= ncol; icol ++)
  219. result [irow] [icol] = NUMrandomGauss (mu, sigma);
  220. return result;
  221. }
  222. inline void MATsin_inplace (const MAT& x) noexcept {
  223. VECsin_inplace (asvector (x));
  224. }
  225. inline void MATsubtract_inplace (const MAT& x, double number) noexcept {
  226. for (integer irow = 1; irow <= x.nrow; irow ++)
  227. for (integer icol = 1; icol <= x.ncol; icol ++)
  228. x [irow] [icol] -= number;
  229. }
  230. inline void MATsubtract_inplace (const MAT& x, const constVEC& y) noexcept {
  231. Melder_assert (x.ncol == y.size);
  232. for (integer irow = 1; irow <= x.nrow; irow ++)
  233. for (integer icol = 1; icol <= x.ncol; icol ++)
  234. x [irow] [icol] -= y [icol];
  235. }
  236. inline void MATsubtractReversed_inplace (const MAT& x, double number) noexcept {
  237. for (integer irow = 1; irow <= x.nrow; irow ++)
  238. for (integer icol = 1; icol <= x.ncol; icol ++)
  239. x [irow] [icol] = number - x [irow] [icol];
  240. }
  241. inline void MATsubtract_inplace (const MAT& x, const constMAT& y) noexcept {
  242. Melder_assert (y.nrow == x.nrow && y.ncol == x.ncol);
  243. for (integer irow = 1; irow <= x.nrow; irow ++)
  244. for (integer icol = 1; icol <= x.ncol; icol ++)
  245. x [irow] [icol] -= y [irow] [icol];
  246. }
  247. inline void MATsubtractReversed_inplace (const MAT& x, const constMAT& y) noexcept {
  248. Melder_assert (y.nrow == x.nrow && y.ncol == x.ncol);
  249. for (integer irow = 1; irow <= x.nrow; irow ++)
  250. for (integer icol = 1; icol <= x.ncol; icol ++)
  251. x [irow] [icol] = y [irow] [icol] - x [irow] [icol];
  252. }
  253. inline autoMAT MATsubtract (const constMAT& x, double y) {
  254. auto result = MATraw (x.nrow, x.ncol);
  255. for (integer irow = 1; irow <= x.nrow; irow ++)
  256. for (integer icol = 1; icol <= x.ncol; icol ++)
  257. result [irow] [icol] = x [irow] [icol] - y;
  258. return result;
  259. }
  260. inline autoMAT MATsubtract (double x, const constMAT& y) {
  261. auto result = MATraw (y.nrow, y.ncol);
  262. for (integer irow = 1; irow <= y.nrow; irow ++)
  263. for (integer icol = 1; icol <= y.ncol; icol ++)
  264. result [irow] [icol] = x - y [irow] [icol];
  265. return result;
  266. }
  267. inline autoMAT MATsubtract (const constMAT& x, const constMAT& y) {
  268. Melder_assert (y.nrow == x.nrow && y.ncol == x.ncol);
  269. auto result = MATraw (x.nrow, x.ncol);
  270. for (integer irow = 1; irow <= x.nrow; irow ++)
  271. for (integer icol = 1; icol <= x.ncol; icol ++)
  272. result [irow] [icol] = x [irow] [icol] - y [irow] [icol];
  273. return result;
  274. }
  275. inline void MATtranspose_inplace_mustBeSquare (const MAT& x) noexcept {
  276. Melder_assert (x.nrow == x.ncol);
  277. integer n = x.nrow;
  278. for (integer i = 1; i < n; i ++)
  279. for (integer j = i + 1; j <= n; j ++)
  280. std::swap (x [i] [j], x [j] [i]);
  281. }
  282. inline void MATtranspose_preallocated (const MAT& target, const constMAT& x) noexcept {
  283. Melder_assert (x.nrow == target.ncol && x.ncol == target.nrow);
  284. for (integer irow = 1; irow <= target.nrow; irow ++)
  285. for (integer icol = 1; icol <= target.ncol; icol ++)
  286. target [irow] [icol] = x [icol] [irow];
  287. }
  288. inline autoMAT MATtranspose (const constMAT& x) {
  289. autoMAT result = MATraw (x.ncol, x.nrow);
  290. MATtranspose_preallocated (result.get(), x);
  291. return result;
  292. }
  293. /* End of file MAT.h */