MatrixMxNTests.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/Math/MathUtils.h>
  9. #include <AzCore/Math/MatrixMxN.h>
  10. #include <AzCore/UnitTest/TestTypes.h>
  11. #include <AZTestShared/Math/MathTestHelpers.h>
  12. namespace UnitTest
  13. {
  14. class Math_MatrixMxN
  15. : public UnitTest::LeakDetectionFixture
  16. {
  17. };
  18. TEST_F(Math_MatrixMxN, TestConstructor)
  19. {
  20. AZ::MatrixMxN m1(3, 2, 5.0f);
  21. EXPECT_EQ(m1.GetRowCount(), 3);
  22. EXPECT_EQ(m1.GetColumnCount(), 2);
  23. for (AZStd::size_t rowIter = 0; rowIter < m1.GetRowCount(); ++rowIter)
  24. {
  25. for (AZStd::size_t colIter = 0; colIter < m1.GetColumnCount(); ++colIter)
  26. {
  27. EXPECT_FLOAT_EQ(m1.GetElement(rowIter, colIter), 5.0f);
  28. }
  29. }
  30. }
  31. TEST_F(Math_MatrixMxN, TestCreate)
  32. {
  33. AZ::MatrixMxN zeros = AZ::MatrixMxN::CreateZero(8, 3);
  34. EXPECT_EQ(zeros.GetRowCount(), 8);
  35. EXPECT_EQ(zeros.GetColumnCount(), 3);
  36. for (AZStd::size_t rowIter = 0; rowIter < zeros.GetRowCount(); ++rowIter)
  37. {
  38. for (AZStd::size_t colIter = 0; colIter < zeros.GetColumnCount(); ++colIter)
  39. {
  40. EXPECT_FLOAT_EQ(zeros.GetElement(rowIter, colIter), 0.0f);
  41. }
  42. }
  43. AZ::MatrixMxN random = AZ::MatrixMxN::CreateRandom(7, 6);
  44. EXPECT_EQ(random.GetRowCount(), 7);
  45. EXPECT_EQ(random.GetColumnCount(), 6);
  46. for (AZStd::size_t rowIter = 0; rowIter < random.GetRowCount(); ++rowIter)
  47. {
  48. for (AZStd::size_t colIter = 0; colIter < random.GetColumnCount(); ++colIter)
  49. {
  50. ASSERT_GE(random.GetElement(rowIter, colIter), 0.0f);
  51. ASSERT_LE(random.GetElement(rowIter, colIter), 1.0f);
  52. }
  53. }
  54. }
  55. TEST_F(Math_MatrixMxN, TestGetSetElement)
  56. {
  57. AZ::MatrixMxN testMatrix(15, 7);
  58. EXPECT_EQ(testMatrix.GetRowCount(), 15);
  59. EXPECT_EQ(testMatrix.GetColumnCount(), 7);
  60. // Initialize each element to be the sum of the indices for that element
  61. for (AZStd::size_t rowIter = 0; rowIter < testMatrix.GetRowCount(); ++rowIter)
  62. {
  63. for (AZStd::size_t colIter = 0; colIter < testMatrix.GetColumnCount(); ++colIter)
  64. {
  65. testMatrix.SetElement(rowIter, colIter, static_cast<float>(2.0f * rowIter + colIter));
  66. }
  67. }
  68. // Validate that each element was stored and can be retrieved correctly
  69. for (AZStd::size_t rowIter = 0; rowIter < testMatrix.GetRowCount(); ++rowIter)
  70. {
  71. for (AZStd::size_t colIter = 0; colIter < testMatrix.GetColumnCount(); ++colIter)
  72. {
  73. EXPECT_FLOAT_EQ(testMatrix.GetElement(rowIter, colIter), static_cast<float>(2.0f * rowIter + colIter));
  74. EXPECT_FLOAT_EQ(testMatrix(rowIter, colIter), static_cast<float>(2.0f * rowIter + colIter));
  75. }
  76. }
  77. }
  78. TEST_F(Math_MatrixMxN, TestTranspose)
  79. {
  80. AZ::MatrixMxN testMatrix(15, 7);
  81. EXPECT_EQ(testMatrix.GetRowCount(), 15);
  82. EXPECT_EQ(testMatrix.GetColumnCount(), 7);
  83. for (AZStd::size_t rowIter = 0; rowIter < testMatrix.GetRowCount(); ++rowIter)
  84. {
  85. for (AZStd::size_t colIter = 0; colIter < testMatrix.GetColumnCount(); ++colIter)
  86. {
  87. testMatrix.SetElement(rowIter, colIter, static_cast<float>(2.0f * rowIter + colIter));
  88. }
  89. }
  90. // Validate that the result has the correct dimensionality and every element was correctly transposed
  91. AZ::MatrixMxN resultMatrix = testMatrix.GetTranspose();
  92. EXPECT_EQ(resultMatrix.GetRowCount(), 7);
  93. EXPECT_EQ(resultMatrix.GetColumnCount(), 15);
  94. for (AZStd::size_t rowIter = 0; rowIter < resultMatrix.GetRowCount(); ++rowIter)
  95. {
  96. for (AZStd::size_t colIter = 0; colIter < resultMatrix.GetColumnCount(); ++colIter)
  97. {
  98. // Originally we stored 2 times the row index + the column index
  99. // The transpose should therefore be storing values of 2 times the column index + the row index
  100. EXPECT_FLOAT_EQ(resultMatrix.GetElement(rowIter, colIter), static_cast<float>(2.0f * colIter + rowIter));
  101. }
  102. }
  103. }
  104. TEST_F(Math_MatrixMxN, TestOperators)
  105. {
  106. AZ::MatrixMxN oneMatrix(5, 3, 1.0f);
  107. AZ::MatrixMxN testMatrix = oneMatrix;
  108. for (AZStd::size_t rowIter = 0; rowIter < oneMatrix.GetRowCount(); ++rowIter)
  109. {
  110. for (AZStd::size_t colIter = 0; colIter < oneMatrix.GetColumnCount(); ++colIter)
  111. {
  112. EXPECT_FLOAT_EQ(oneMatrix.GetElement(rowIter, colIter), 1.0f);
  113. }
  114. }
  115. testMatrix /= 2.0f;
  116. for (AZStd::size_t rowIter = 0; rowIter < testMatrix.GetRowCount(); ++rowIter)
  117. {
  118. for (AZStd::size_t colIter = 0; colIter < testMatrix.GetColumnCount(); ++colIter)
  119. {
  120. EXPECT_FLOAT_EQ(testMatrix.GetElement(rowIter, colIter), 0.5f);
  121. }
  122. }
  123. testMatrix *= 2.0f;
  124. for (AZStd::size_t rowIter = 0; rowIter < testMatrix.GetRowCount(); ++rowIter)
  125. {
  126. for (AZStd::size_t colIter = 0; colIter < testMatrix.GetColumnCount(); ++colIter)
  127. {
  128. EXPECT_FLOAT_EQ(testMatrix.GetElement(rowIter, colIter), 1.0f);
  129. }
  130. }
  131. testMatrix *= 2.0f;
  132. testMatrix += oneMatrix;
  133. for (AZStd::size_t rowIter = 0; rowIter < testMatrix.GetRowCount(); ++rowIter)
  134. {
  135. for (AZStd::size_t colIter = 0; colIter < testMatrix.GetColumnCount(); ++colIter)
  136. {
  137. EXPECT_FLOAT_EQ(testMatrix.GetElement(rowIter, colIter), 3.0f);
  138. }
  139. }
  140. testMatrix -= oneMatrix;
  141. for (AZStd::size_t rowIter = 0; rowIter < testMatrix.GetRowCount(); ++rowIter)
  142. {
  143. for (AZStd::size_t colIter = 0; colIter < testMatrix.GetColumnCount(); ++colIter)
  144. {
  145. EXPECT_FLOAT_EQ(testMatrix.GetElement(rowIter, colIter), 2.0f);
  146. }
  147. }
  148. testMatrix *= 2.0f;
  149. for (AZStd::size_t rowIter = 0; rowIter < testMatrix.GetRowCount(); ++rowIter)
  150. {
  151. for (AZStd::size_t colIter = 0; colIter < testMatrix.GetColumnCount(); ++colIter)
  152. {
  153. EXPECT_FLOAT_EQ(testMatrix.GetElement(rowIter, colIter), 4.0f);
  154. }
  155. }
  156. testMatrix += 7.0f;
  157. for (AZStd::size_t rowIter = 0; rowIter < testMatrix.GetRowCount(); ++rowIter)
  158. {
  159. for (AZStd::size_t colIter = 0; colIter < testMatrix.GetColumnCount(); ++colIter)
  160. {
  161. EXPECT_FLOAT_EQ(testMatrix.GetElement(rowIter, colIter), 11.0f);
  162. }
  163. }
  164. testMatrix -= 12.0f;
  165. for (AZStd::size_t rowIter = 0; rowIter < testMatrix.GetRowCount(); ++rowIter)
  166. {
  167. for (AZStd::size_t colIter = 0; colIter < testMatrix.GetColumnCount(); ++colIter)
  168. {
  169. EXPECT_FLOAT_EQ(testMatrix.GetElement(rowIter, colIter), -1.0f);
  170. }
  171. }
  172. }
  173. TEST_F(Math_MatrixMxN, TestFloorCeilRound)
  174. {
  175. AZ::MatrixMxN mat1 = AZ::MatrixMxN(7, 3, 4.1f);
  176. AZ::MatrixMxN floor = mat1.GetFloor();
  177. for (AZStd::size_t rowIter = 0; rowIter < floor.GetRowCount(); ++rowIter)
  178. {
  179. for (AZStd::size_t colIter = 0; colIter < floor.GetColumnCount(); ++colIter)
  180. {
  181. EXPECT_FLOAT_EQ(floor.GetElement(rowIter, colIter), 4.0f);
  182. }
  183. }
  184. AZ::MatrixMxN ceil = mat1.GetCeil();
  185. for (AZStd::size_t rowIter = 0; rowIter < floor.GetRowCount(); ++rowIter)
  186. {
  187. for (AZStd::size_t colIter = 0; colIter < floor.GetColumnCount(); ++colIter)
  188. {
  189. EXPECT_FLOAT_EQ(ceil.GetElement(rowIter, colIter), 5.0f);
  190. }
  191. }
  192. AZ::MatrixMxN round = mat1.GetRound();
  193. for (AZStd::size_t rowIter = 0; rowIter < floor.GetRowCount(); ++rowIter)
  194. {
  195. for (AZStd::size_t colIter = 0; colIter < floor.GetColumnCount(); ++colIter)
  196. {
  197. EXPECT_FLOAT_EQ(round.GetElement(rowIter, colIter), 4.0f);
  198. }
  199. }
  200. AZ::MatrixMxN vec2 = AZ::MatrixMxN(7, 3, 4.5f);
  201. AZ::MatrixMxN tie = vec2.GetRound();
  202. for (AZStd::size_t rowIter = 0; rowIter < floor.GetRowCount(); ++rowIter)
  203. {
  204. for (AZStd::size_t colIter = 0; colIter < floor.GetColumnCount(); ++colIter)
  205. {
  206. EXPECT_FLOAT_EQ(tie.GetElement(rowIter, colIter), 4.0f);
  207. }
  208. }
  209. }
  210. TEST_F(Math_MatrixMxN, TestMinMaxClamp)
  211. {
  212. AZ::MatrixMxN random = AZ::MatrixMxN::CreateRandom(7, 3); // random matrix with elements between 0 and 1
  213. // min should be between 0.0 and 0.5
  214. AZ::MatrixMxN min = random.GetMin(AZ::MatrixMxN(7, 3, 0.5f));
  215. for (AZStd::size_t rowIter = 0; rowIter < min.GetRowCount(); ++rowIter)
  216. {
  217. for (AZStd::size_t colIter = 0; colIter < min.GetColumnCount(); ++colIter)
  218. {
  219. EXPECT_LE(min.GetElement(rowIter, colIter), 0.5f);
  220. }
  221. }
  222. // max should be between 0.5 and 1.0
  223. AZ::MatrixMxN max = random.GetMax(AZ::MatrixMxN(7, 3, 0.5f));
  224. for (AZStd::size_t rowIter = 0; rowIter < max.GetRowCount(); ++rowIter)
  225. {
  226. for (AZStd::size_t colIter = 0; colIter < max.GetColumnCount(); ++colIter)
  227. {
  228. EXPECT_GE(max.GetElement(rowIter, colIter), 0.5f);
  229. }
  230. }
  231. // clamp should be between 0.1 and 0.9
  232. AZ::MatrixMxN clamp = random.GetClamp(AZ::MatrixMxN(7,3, 0.1f), AZ::MatrixMxN(7, 3, 0.9f));
  233. for (AZStd::size_t rowIter = 0; rowIter < clamp.GetRowCount(); ++rowIter)
  234. {
  235. for (AZStd::size_t colIter = 0; colIter < clamp.GetColumnCount(); ++colIter)
  236. {
  237. EXPECT_GE(clamp.GetElement(rowIter, colIter), 0.1f);
  238. EXPECT_LE(clamp.GetElement(rowIter, colIter), 0.9f);
  239. }
  240. }
  241. }
  242. TEST_F(Math_MatrixMxN, TestSquareAbs)
  243. {
  244. AZ::MatrixMxN random = AZ::MatrixMxN::CreateRandom(200, 100); // random vector between 0 and 1
  245. random -= 0.5f; // random vector between -0.5 and 0.5
  246. // absRand should be between 0.0 and 0.5
  247. AZ::MatrixMxN absRand = random.GetAbs();
  248. for (AZStd::size_t rowIter = 0; rowIter < absRand.GetRowCount(); ++rowIter)
  249. {
  250. for (AZStd::size_t colIter = 0; colIter < absRand.GetColumnCount(); ++colIter)
  251. {
  252. EXPECT_GE(absRand.GetElement(rowIter, colIter), 0.0f);
  253. EXPECT_LE(absRand.GetElement(rowIter, colIter), 0.5f);
  254. }
  255. }
  256. // sqRand should be between -0.25 and 0.25
  257. AZ::MatrixMxN sqRand = random.GetSquare();
  258. for (AZStd::size_t rowIter = 0; rowIter < sqRand.GetRowCount(); ++rowIter)
  259. {
  260. for (AZStd::size_t colIter = 0; colIter < sqRand.GetColumnCount(); ++colIter)
  261. {
  262. EXPECT_GE(sqRand.GetElement(rowIter, colIter), -0.25f);
  263. EXPECT_LE(sqRand.GetElement(rowIter, colIter), 0.25f);
  264. }
  265. }
  266. }
  267. TEST_F(Math_MatrixMxN, TestOuterProduct)
  268. {
  269. const float lhsElements[] =
  270. {
  271. 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f
  272. };
  273. const float rhsElements[] =
  274. {
  275. 4.0f, 3.0f, 2.0f, 1.0f, 0.0f
  276. };
  277. const AZ::VectorN lhsVector = AZ::VectorN::CreateFromFloats(7, lhsElements);
  278. const AZ::VectorN rhsVector = AZ::VectorN::CreateFromFloats(5, rhsElements);
  279. AZ::MatrixMxN output = AZ::MatrixMxN::CreateZero(7, 5);
  280. AZ::OuterProduct(lhsVector, rhsVector, output);
  281. for (AZStd::size_t rowIter = 0; rowIter < output.GetRowCount(); ++rowIter)
  282. {
  283. for (AZStd::size_t colIter = 0; colIter < output.GetColumnCount(); ++colIter)
  284. {
  285. const float expectedOutput = float(rowIter) * (4.0f - float(colIter));
  286. const float actualOutput = output.GetElement(rowIter, colIter);
  287. EXPECT_FLOAT_EQ(actualOutput, expectedOutput);
  288. }
  289. }
  290. }
  291. TEST_F(Math_MatrixMxN, TestVectorMatrixMultiply)
  292. {
  293. const float matrixElements[] =
  294. {
  295. 1.0f, 0.0f, 2.0f, 0.0f, 1.0f, 0.0f, 3.0f,
  296. 0.0f, 1.0f, 0.0f, 2.0f, 0.0f, 1.0f, 3.0f,
  297. 0.0f, 0.0f, 1.0f, 0.0f, 2.0f, 0.0f, 3.0f,
  298. 1.0f, 0.0f, 2.0f, 0.0f, 1.0f, 0.0f, 3.0f,
  299. 0.0f, 1.0f, 0.0f, 2.0f, 0.0f, 1.0f, 3.0f,
  300. 0.0f, 0.0f, 1.0f, 0.0f, 2.0f, 0.0f, 3.0f,
  301. };
  302. const float vectorElements[] =
  303. {
  304. 1.0f, 0.0f, 2.0f, 0.0f, 3.0f, 0.0f, 1.0f
  305. };
  306. const float outputElements[] =
  307. {
  308. 1.0f + 0.0f + 4.0f + 0.0f + 3.0f + 0.0f + 3.0f,
  309. 0.0f + 0.0f + 0.0f + 0.0f + 0.0f + 0.0f + 3.0f,
  310. 0.0f + 0.0f + 2.0f + 0.0f + 6.0f + 0.0f + 3.0f,
  311. 1.0f + 0.0f + 4.0f + 0.0f + 3.0f + 0.0f + 3.0f,
  312. 0.0f + 0.0f + 0.0f + 0.0f + 0.0f + 0.0f + 3.0f,
  313. 0.0f + 0.0f + 2.0f + 0.0f + 6.0f + 0.0f + 3.0f,
  314. };
  315. const AZ::MatrixMxN matrix = AZ::MatrixMxN::CreateFromPackedFloats(6, 7, matrixElements);
  316. const AZ::VectorN vector = AZ::VectorN::CreateFromFloats(7, vectorElements);
  317. AZ::VectorN output = AZ::VectorN::CreateZero(6);
  318. VectorMatrixMultiply(matrix, vector, output);
  319. for (AZStd::size_t iter = 0; iter < output.GetDimensionality(); ++iter)
  320. {
  321. EXPECT_FLOAT_EQ(output.GetElement(iter), outputElements[iter]);
  322. }
  323. }
  324. TEST_F(Math_MatrixMxN, TestVectorMatrixLeftMultiply)
  325. {
  326. const float matrixElements[] =
  327. {
  328. 1.0f, 0.0f, 2.0f, 0.0f, 1.0f, 0.0f, 3.0f,
  329. 0.0f, 1.0f, 0.0f, 2.0f, 0.0f, 1.0f, 3.0f,
  330. 0.0f, 0.0f, 1.0f, 0.0f, 2.0f, 0.0f, 3.0f,
  331. 1.0f, 0.0f, 2.0f, 0.0f, 1.0f, 0.0f, 3.0f,
  332. 0.0f, 1.0f, 0.0f, 2.0f, 0.0f, 1.0f, 3.0f,
  333. 0.0f, 0.0f, 1.0f, 0.0f, 2.0f, 0.0f, 3.0f,
  334. };
  335. const float vectorElements[] =
  336. {
  337. 1.0f, 0.0f, 2.0f, 0.0f, 3.0f, 0.0f
  338. };
  339. const float outputElements[] =
  340. {
  341. 1.0f + 0.0f + 0.0f + 0.0f + 0.0f + 0.0f,
  342. 0.0f + 0.0f + 0.0f + 0.0f + 3.0f + 0.0f,
  343. 2.0f + 0.0f + 2.0f + 0.0f + 0.0f + 0.0f,
  344. 0.0f + 0.0f + 0.0f + 0.0f + 6.0f + 0.0f,
  345. 1.0f + 0.0f + 4.0f + 0.0f + 0.0f + 0.0f,
  346. 0.0f + 0.0f + 0.0f + 0.0f + 3.0f + 0.0f,
  347. 3.0f + 0.0f + 6.0f + 0.0f + 9.0f + 0.0f,
  348. };
  349. const AZ::MatrixMxN matrix = AZ::MatrixMxN::CreateFromPackedFloats(6, 7, matrixElements);
  350. const AZ::VectorN vector = AZ::VectorN::CreateFromFloats(6, vectorElements);
  351. AZ::VectorN output = AZ::VectorN::CreateZero(7);
  352. VectorMatrixMultiplyLeft(vector, matrix, output);
  353. for (AZStd::size_t iter = 0; iter < output.GetDimensionality(); ++iter)
  354. {
  355. EXPECT_FLOAT_EQ(output.GetElement(iter), outputElements[iter]);
  356. }
  357. }
  358. TEST_F(Math_MatrixMxN, TestMatrixMatrixMultiplySingleBlock)
  359. {
  360. // 3 x 4
  361. const float lhsElements[] =
  362. {
  363. 1.0f, 2.0f, 3.0f, 4.0f,
  364. 5.0f, 6.0f, 7.0f, 8.0f,
  365. 9.0f, 0.0f, 1.0f, 2.0f,
  366. };
  367. // 4 x 3
  368. const float rhsElements[] =
  369. {
  370. 1.0f, 2.0f, 3.0f,
  371. 4.0f, 5.0f, 6.0f,
  372. 7.0f, 8.0f, 9.0f,
  373. 0.0f, 1.0f, 2.0f,
  374. };
  375. // 3 x 3
  376. const float outputElements[] =
  377. {
  378. 30.0f, 40.0f, 50.0f,
  379. 78.0f, 104.0f, 130.0f,
  380. 16.0f, 28.0f, 40.0f,
  381. };
  382. const AZ::MatrixMxN lhs = AZ::MatrixMxN::CreateFromPackedFloats(3, 4, lhsElements);
  383. const AZ::MatrixMxN rhs = AZ::MatrixMxN::CreateFromPackedFloats(4, 3, rhsElements);
  384. AZ::MatrixMxN output = AZ::MatrixMxN::CreateZero(3, 3);
  385. AZ::MatrixMatrixMultiply(lhs, rhs, output);
  386. const float* checkResult = outputElements;
  387. for (AZStd::size_t rowIter = 0; rowIter < output.GetRowCount(); ++rowIter)
  388. {
  389. for (AZStd::size_t colIter = 0; colIter < output.GetColumnCount(); ++colIter)
  390. {
  391. EXPECT_FLOAT_EQ(output.GetElement(rowIter, colIter), *checkResult);
  392. ++checkResult;
  393. }
  394. }
  395. }
  396. TEST_F(Math_MatrixMxN, TestMatrixMatrixMultiply)
  397. {
  398. // 5 x 7
  399. const float lhsElements[] =
  400. {
  401. 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f,
  402. 8.0f, 9.0f, 0.0f, 1.0f, 2.0f, 3.0f, 4.0f,
  403. 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 0.0f, 1.0f,
  404. 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f,
  405. 9.0f, 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f,
  406. };
  407. // 7 x 6
  408. const float rhsElements[] =
  409. {
  410. 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f,
  411. 7.0f, 8.0f, 9.0f, 0.0f, 1.0f, 2.0f,
  412. 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f,
  413. 9.0f, 0.0f, 1.0f, 2.0f, 3.0f, 4.0f,
  414. 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 0.0f,
  415. 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f,
  416. 7.0f, 8.0f, 9.0f, 0.0f, 1.0f, 2.0f,
  417. };
  418. // 5 x 6
  419. const float outputElements[] =
  420. {
  421. 140.0f, 128.0f, 156.0f, 94.0f, 122.0f, 100.0f,
  422. 121.0f, 138.0f, 165.0f, 62.0f, 89.0f, 96.0f,
  423. 192.0f, 148.0f, 184.0f, 150.0f, 186.0f, 132.0f,
  424. 173.0f, 158.0f, 193.0f, 118.0f, 153.0f, 128.0f,
  425. 84.0f, 88.0f, 112.0f, 86.0f, 110.0f, 104.0f,
  426. };
  427. AZ::MatrixMxN lhs = AZ::MatrixMxN::CreateFromPackedFloats(5, 7, lhsElements);
  428. AZ::MatrixMxN rhs = AZ::MatrixMxN::CreateFromPackedFloats(7, 6, rhsElements);
  429. AZ::MatrixMxN output = AZ::MatrixMxN::CreateZero(5, 6);
  430. AZ::MatrixMatrixMultiply(lhs, rhs, output);
  431. const float* checkResult = outputElements;
  432. for (AZStd::size_t rowIter = 0; rowIter < output.GetRowCount(); ++rowIter)
  433. {
  434. for (AZStd::size_t colIter = 0; colIter < output.GetColumnCount(); ++colIter)
  435. {
  436. EXPECT_FLOAT_EQ(output.GetElement(rowIter, colIter), *checkResult);
  437. ++checkResult;
  438. }
  439. }
  440. AZ::MatrixMxN result = lhs * rhs;
  441. checkResult = outputElements;
  442. for (AZStd::size_t rowIter = 0; rowIter < result.GetRowCount(); ++rowIter)
  443. {
  444. for (AZStd::size_t colIter = 0; colIter < result.GetColumnCount(); ++colIter)
  445. {
  446. EXPECT_FLOAT_EQ(result.GetElement(rowIter, colIter), *checkResult);
  447. ++checkResult;
  448. }
  449. }
  450. }
  451. }