1/* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "Test.h" 9#include "TestClassDef.h" 10#include "SkMatrix44.h" 11 12static bool nearly_equal_double(double a, double b) { 13 const double tolerance = 1e-7; 14 double diff = a - b; 15 if (diff < 0) 16 diff = -diff; 17 return diff <= tolerance; 18} 19 20static bool nearly_equal_mscalar(SkMScalar a, SkMScalar b) { 21 const SkMScalar tolerance = SK_MScalar1 / 200000; 22 23 return SkTAbs<SkMScalar>(a - b) <= tolerance; 24} 25 26static bool nearly_equal_scalar(SkScalar a, SkScalar b) { 27 // Note that we get more compounded error for multiple operations when 28 // SK_SCALAR_IS_FIXED. 29#ifdef SK_SCALAR_IS_FLOAT 30 const SkScalar tolerance = SK_Scalar1 / 200000; 31#else 32 const SkScalar tolerance = SK_Scalar1 / 1024; 33#endif 34 35 return SkScalarAbs(a - b) <= tolerance; 36} 37 38template <typename T> void assert16(skiatest::Reporter* reporter, const T data[], 39 T m0, T m1, T m2, T m3, 40 T m4, T m5, T m6, T m7, 41 T m8, T m9, T m10, T m11, 42 T m12, T m13, T m14, T m15) { 43 REPORTER_ASSERT(reporter, data[0] == m0); 44 REPORTER_ASSERT(reporter, data[1] == m1); 45 REPORTER_ASSERT(reporter, data[2] == m2); 46 REPORTER_ASSERT(reporter, data[3] == m3); 47 48 REPORTER_ASSERT(reporter, data[4] == m4); 49 REPORTER_ASSERT(reporter, data[5] == m5); 50 REPORTER_ASSERT(reporter, data[6] == m6); 51 REPORTER_ASSERT(reporter, data[7] == m7); 52 53 REPORTER_ASSERT(reporter, data[8] == m8); 54 REPORTER_ASSERT(reporter, data[9] == m9); 55 REPORTER_ASSERT(reporter, data[10] == m10); 56 REPORTER_ASSERT(reporter, data[11] == m11); 57 58 REPORTER_ASSERT(reporter, data[12] == m12); 59 REPORTER_ASSERT(reporter, data[13] == m13); 60 REPORTER_ASSERT(reporter, data[14] == m14); 61 REPORTER_ASSERT(reporter, data[15] == m15); 62} 63 64static bool nearly_equal(const SkMatrix44& a, const SkMatrix44& b) { 65 for (int i = 0; i < 4; ++i) { 66 for (int j = 0; j < 4; ++j) { 67 if (!nearly_equal_mscalar(a.get(i, j), b.get(i, j))) { 68 SkDebugf("not equal %g %g\n", a.get(i, j), b.get(i, j)); 69 return false; 70 } 71 } 72 } 73 return true; 74} 75 76static bool is_identity(const SkMatrix44& m) { 77 SkMatrix44 identity(SkMatrix44::kIdentity_Constructor); 78 return nearly_equal(m, identity); 79} 80 81/////////////////////////////////////////////////////////////////////////////// 82static bool bits_isonly(int value, int mask) { 83 return 0 == (value & ~mask); 84} 85 86static void test_constructor(skiatest::Reporter* reporter) { 87 // Allocate a matrix on the heap 88 SkMatrix44* placeholderMatrix = new SkMatrix44(SkMatrix44::kUninitialized_Constructor); 89 SkAutoTDelete<SkMatrix44> deleteMe(placeholderMatrix); 90 91 for (int row = 0; row < 4; ++row) { 92 for (int col = 0; col < 4; ++col) { 93 placeholderMatrix->setDouble(row, col, row * col); 94 } 95 } 96 97 // Use placement-new syntax to trigger the constructor on top of the heap 98 // address we already initialized. This allows us to check that the 99 // constructor did avoid initializing the matrix contents. 100 SkMatrix44* testMatrix = new(placeholderMatrix) SkMatrix44(SkMatrix44::kUninitialized_Constructor); 101 REPORTER_ASSERT(reporter, testMatrix == placeholderMatrix); 102 REPORTER_ASSERT(reporter, !testMatrix->isIdentity()); 103 for (int row = 0; row < 4; ++row) { 104 for (int col = 0; col < 4; ++col) { 105 REPORTER_ASSERT(reporter, nearly_equal_double(row * col, testMatrix->getDouble(row, col))); 106 } 107 } 108 109 // Verify that kIdentity_Constructor really does initialize to an identity matrix. 110 testMatrix = 0; 111 testMatrix = new(placeholderMatrix) SkMatrix44(SkMatrix44::kIdentity_Constructor); 112 REPORTER_ASSERT(reporter, testMatrix == placeholderMatrix); 113 REPORTER_ASSERT(reporter, testMatrix->isIdentity()); 114 REPORTER_ASSERT(reporter, *testMatrix == SkMatrix44::I()); 115} 116 117static void test_translate(skiatest::Reporter* reporter) { 118 SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor); 119 SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor); 120 121 mat.setTranslate(0, 0, 0); 122 REPORTER_ASSERT(reporter, bits_isonly(mat.getType(), SkMatrix44::kIdentity_Mask)); 123 mat.setTranslate(1, 2, 3); 124 REPORTER_ASSERT(reporter, bits_isonly(mat.getType(), SkMatrix44::kTranslate_Mask)); 125 REPORTER_ASSERT(reporter, mat.invert(&inverse)); 126 REPORTER_ASSERT(reporter, bits_isonly(inverse.getType(), SkMatrix44::kTranslate_Mask)); 127 128 SkMatrix44 a(SkMatrix44::kUninitialized_Constructor); 129 SkMatrix44 b(SkMatrix44::kUninitialized_Constructor); 130 SkMatrix44 c(SkMatrix44::kUninitialized_Constructor); 131 a.set3x3(1, 2, 3, 4, 5, 6, 7, 8, 9); 132 b.setTranslate(10, 11, 12); 133 134 c.setConcat(a, b); 135 mat = a; 136 mat.preTranslate(10, 11, 12); 137 REPORTER_ASSERT(reporter, mat == c); 138 139 c.setConcat(b, a); 140 mat = a; 141 mat.postTranslate(10, 11, 12); 142 REPORTER_ASSERT(reporter, mat == c); 143} 144 145static void test_scale(skiatest::Reporter* reporter) { 146 SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor); 147 SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor); 148 149 mat.setScale(1, 1, 1); 150 REPORTER_ASSERT(reporter, bits_isonly(mat.getType(), SkMatrix44::kIdentity_Mask)); 151 mat.setScale(1, 2, 3); 152 REPORTER_ASSERT(reporter, bits_isonly(mat.getType(), SkMatrix44::kScale_Mask)); 153 REPORTER_ASSERT(reporter, mat.invert(&inverse)); 154 REPORTER_ASSERT(reporter, bits_isonly(inverse.getType(), SkMatrix44::kScale_Mask)); 155 156 SkMatrix44 a(SkMatrix44::kUninitialized_Constructor); 157 SkMatrix44 b(SkMatrix44::kUninitialized_Constructor); 158 SkMatrix44 c(SkMatrix44::kUninitialized_Constructor); 159 a.set3x3(1, 2, 3, 4, 5, 6, 7, 8, 9); 160 b.setScale(10, 11, 12); 161 162 c.setConcat(a, b); 163 mat = a; 164 mat.preScale(10, 11, 12); 165 REPORTER_ASSERT(reporter, mat == c); 166 167 c.setConcat(b, a); 168 mat = a; 169 mat.postScale(10, 11, 12); 170 REPORTER_ASSERT(reporter, mat == c); 171} 172 173static void make_i(SkMatrix44* mat) { mat->setIdentity(); } 174static void make_t(SkMatrix44* mat) { mat->setTranslate(1, 2, 3); } 175static void make_s(SkMatrix44* mat) { mat->setScale(1, 2, 3); } 176static void make_st(SkMatrix44* mat) { 177 mat->setScale(1, 2, 3); 178 mat->postTranslate(1, 2, 3); 179} 180static void make_a(SkMatrix44* mat) { 181 mat->setRotateDegreesAbout(1, 2, 3, 45); 182} 183static void make_p(SkMatrix44* mat) { 184 SkMScalar data[] = { 185 1, 2, 3, 4, 5, 6, 7, 8, 186 1, 2, 3, 4, 5, 6, 7, 8, 187 }; 188 mat->setRowMajor(data); 189} 190 191typedef void (*Make44Proc)(SkMatrix44*); 192 193static const Make44Proc gMakeProcs[] = { 194 make_i, make_t, make_s, make_st, make_a, make_p 195}; 196 197static void test_map2(skiatest::Reporter* reporter, const SkMatrix44& mat) { 198 SkMScalar src2[] = { 1, 2 }; 199 SkMScalar src4[] = { src2[0], src2[1], 0, 1 }; 200 SkMScalar dstA[4], dstB[4]; 201 202 for (int i = 0; i < 4; ++i) { 203 dstA[i] = 123456789; 204 dstB[i] = 987654321; 205 } 206 207 mat.map2(src2, 1, dstA); 208 mat.mapMScalars(src4, dstB); 209 210 for (int i = 0; i < 4; ++i) { 211 REPORTER_ASSERT(reporter, dstA[i] == dstB[i]); 212 } 213} 214 215static void test_map2(skiatest::Reporter* reporter) { 216 SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor); 217 218 for (size_t i = 0; i < SK_ARRAY_COUNT(gMakeProcs); ++i) { 219 gMakeProcs[i](&mat); 220 test_map2(reporter, mat); 221 } 222} 223 224static void test_gettype(skiatest::Reporter* reporter) { 225 SkMatrix44 matrix(SkMatrix44::kIdentity_Constructor); 226 227 REPORTER_ASSERT(reporter, matrix.isIdentity()); 228 REPORTER_ASSERT(reporter, SkMatrix44::kIdentity_Mask == matrix.getType()); 229 230 int expectedMask; 231 232 matrix.set(1, 1, 0); 233 expectedMask = SkMatrix44::kScale_Mask; 234 REPORTER_ASSERT(reporter, matrix.getType() == expectedMask); 235 236 matrix.set(0, 3, 1); // translate-x 237 expectedMask |= SkMatrix44::kTranslate_Mask; 238 REPORTER_ASSERT(reporter, matrix.getType() == expectedMask); 239 240 matrix.set(2, 0, 1); 241 expectedMask |= SkMatrix44::kAffine_Mask; 242 REPORTER_ASSERT(reporter, matrix.getType() == expectedMask); 243 244 matrix.set(3, 2, 1); 245 REPORTER_ASSERT(reporter, matrix.getType() & SkMatrix44::kPerspective_Mask); 246 247 // ensure that negative zero is treated as zero 248 SkMScalar dx = 0; 249 SkMScalar dy = 0; 250 SkMScalar dz = 0; 251 matrix.setTranslate(-dx, -dy, -dz); 252 REPORTER_ASSERT(reporter, matrix.isIdentity()); 253 matrix.preTranslate(-dx, -dy, -dz); 254 REPORTER_ASSERT(reporter, matrix.isIdentity()); 255 matrix.postTranslate(-dx, -dy, -dz); 256 REPORTER_ASSERT(reporter, matrix.isIdentity()); 257} 258 259static void test_common_angles(skiatest::Reporter* reporter) { 260 SkMatrix44 rot(SkMatrix44::kUninitialized_Constructor); 261 // Test precision of rotation in common cases 262 int common_angles[] = { 0, 90, -90, 180, -180, 270, -270, 360, -360 }; 263 for (int i = 0; i < 9; ++i) { 264 rot.setRotateDegreesAbout(0, 0, -1, SkIntToScalar(common_angles[i])); 265 266 SkMatrix rot3x3 = rot; 267 REPORTER_ASSERT(reporter, rot3x3.rectStaysRect()); 268 } 269} 270 271static void test_concat(skiatest::Reporter* reporter) { 272 int i; 273 SkMatrix44 a(SkMatrix44::kUninitialized_Constructor); 274 SkMatrix44 b(SkMatrix44::kUninitialized_Constructor); 275 SkMatrix44 c(SkMatrix44::kUninitialized_Constructor); 276 SkMatrix44 d(SkMatrix44::kUninitialized_Constructor); 277 278 a.setTranslate(10, 10, 10); 279 b.setScale(2, 2, 2); 280 281 SkScalar src[8] = { 282 0, 0, 0, 1, 283 1, 1, 1, 1 284 }; 285 SkScalar dst[8]; 286 287 c.setConcat(a, b); 288 289 d = a; 290 d.preConcat(b); 291 REPORTER_ASSERT(reporter, d == c); 292 293 c.mapScalars(src, dst); c.mapScalars(src + 4, dst + 4); 294 for (i = 0; i < 3; ++i) { 295 REPORTER_ASSERT(reporter, 10 == dst[i]); 296 REPORTER_ASSERT(reporter, 12 == dst[i + 4]); 297 } 298 299 c.setConcat(b, a); 300 301 d = a; 302 d.postConcat(b); 303 REPORTER_ASSERT(reporter, d == c); 304 305 c.mapScalars(src, dst); c.mapScalars(src + 4, dst + 4); 306 for (i = 0; i < 3; ++i) { 307 REPORTER_ASSERT(reporter, 20 == dst[i]); 308 REPORTER_ASSERT(reporter, 22 == dst[i + 4]); 309 } 310} 311 312static void test_determinant(skiatest::Reporter* reporter) { 313 SkMatrix44 a(SkMatrix44::kIdentity_Constructor); 314 REPORTER_ASSERT(reporter, nearly_equal_double(1, a.determinant())); 315 a.set(1, 1, 2); 316 REPORTER_ASSERT(reporter, nearly_equal_double(2, a.determinant())); 317 SkMatrix44 b(SkMatrix44::kUninitialized_Constructor); 318 REPORTER_ASSERT(reporter, a.invert(&b)); 319 REPORTER_ASSERT(reporter, nearly_equal_double(0.5, b.determinant())); 320 SkMatrix44 c = b = a; 321 c.set(0, 1, 4); 322 b.set(1, 0, 4); 323 REPORTER_ASSERT(reporter, 324 nearly_equal_double(a.determinant(), 325 b.determinant())); 326 SkMatrix44 d = a; 327 d.set(0, 0, 8); 328 REPORTER_ASSERT(reporter, nearly_equal_double(16, d.determinant())); 329 330 SkMatrix44 e = a; 331 e.postConcat(d); 332 REPORTER_ASSERT(reporter, nearly_equal_double(32, e.determinant())); 333 e.set(0, 0, 0); 334 REPORTER_ASSERT(reporter, nearly_equal_double(0, e.determinant())); 335} 336 337static void test_invert(skiatest::Reporter* reporter) { 338 SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor); 339 double inverseData[16]; 340 341 SkMatrix44 identity(SkMatrix44::kIdentity_Constructor); 342 identity.invert(&inverse); 343 inverse.asRowMajord(inverseData); 344 assert16<double>(reporter, inverseData, 345 1, 0, 0, 0, 346 0, 1, 0, 0, 347 0, 0, 1, 0, 348 0, 0, 0, 1); 349 350 SkMatrix44 translation(SkMatrix44::kUninitialized_Constructor); 351 translation.setTranslate(2, 3, 4); 352 translation.invert(&inverse); 353 inverse.asRowMajord(inverseData); 354 assert16<double>(reporter, inverseData, 355 1, 0, 0, -2, 356 0, 1, 0, -3, 357 0, 0, 1, -4, 358 0, 0, 0, 1); 359 360 SkMatrix44 scale(SkMatrix44::kUninitialized_Constructor); 361 scale.setScale(2, 4, 8); 362 scale.invert(&inverse); 363 inverse.asRowMajord(inverseData); 364 assert16<double>(reporter, inverseData, 365 0.5, 0, 0, 0, 366 0, 0.25, 0, 0, 367 0, 0, 0.125, 0, 368 0, 0, 0, 1); 369 370 SkMatrix44 scaleTranslation(SkMatrix44::kUninitialized_Constructor); 371 scaleTranslation.setScale(10, 100, 1000); 372 scaleTranslation.preTranslate(2, 3, 4); 373 scaleTranslation.invert(&inverse); 374 inverse.asRowMajord(inverseData); 375 assert16<double>(reporter, inverseData, 376 0.1, 0, 0, -2, 377 0, 0.01, 0, -3, 378 0, 0, 0.001, -4, 379 0, 0, 0, 1); 380 381 SkMatrix44 rotation(SkMatrix44::kUninitialized_Constructor); 382 rotation.setRotateDegreesAbout(0, 0, 1, 90); 383 rotation.invert(&inverse); 384 SkMatrix44 expected(SkMatrix44::kUninitialized_Constructor); 385 double expectedInverseRotation[16] = 386 {0, 1, 0, 0, 387 -1, 0, 0, 0, 388 0, 0, 1, 0, 389 0, 0, 0, 1}; 390 expected.setRowMajord(expectedInverseRotation); 391 REPORTER_ASSERT(reporter, nearly_equal(expected, inverse)); 392 393 SkMatrix44 affine(SkMatrix44::kUninitialized_Constructor); 394 affine.setRotateDegreesAbout(0, 0, 1, 90); 395 affine.preScale(10, 20, 100); 396 affine.preTranslate(2, 3, 4); 397 affine.invert(&inverse); 398 double expectedInverseAffine[16] = 399 {0, 0.1, 0, -2, 400 -0.05, 0, 0, -3, 401 0, 0, 0.01, -4, 402 0, 0, 0, 1}; 403 expected.setRowMajord(expectedInverseAffine); 404 REPORTER_ASSERT(reporter, nearly_equal(expected, inverse)); 405 406 SkMatrix44 perspective(SkMatrix44::kIdentity_Constructor); 407 perspective.setDouble(3, 2, 1.0); 408 perspective.invert(&inverse); 409 double expectedInversePerspective[16] = 410 {1, 0, 0, 0, 411 0, 1, 0, 0, 412 0, 0, 1, 0, 413 0, 0, -1, 1}; 414 expected.setRowMajord(expectedInversePerspective); 415 REPORTER_ASSERT(reporter, nearly_equal(expected, inverse)); 416 417 SkMatrix44 affineAndPerspective(SkMatrix44::kIdentity_Constructor); 418 affineAndPerspective.setDouble(3, 2, 1.0); 419 affineAndPerspective.preScale(10, 20, 100); 420 affineAndPerspective.preTranslate(2, 3, 4); 421 affineAndPerspective.invert(&inverse); 422 double expectedInverseAffineAndPerspective[16] = 423 {0.1, 0, 2, -2, 424 0, 0.05, 3, -3, 425 0, 0, 4.01, -4, 426 0, 0, -1, 1}; 427 expected.setRowMajord(expectedInverseAffineAndPerspective); 428 REPORTER_ASSERT(reporter, nearly_equal(expected, inverse)); 429} 430 431static void test_transpose(skiatest::Reporter* reporter) { 432 SkMatrix44 a(SkMatrix44::kUninitialized_Constructor); 433 SkMatrix44 b(SkMatrix44::kUninitialized_Constructor); 434 435 int i = 0; 436 for (int row = 0; row < 4; ++row) { 437 for (int col = 0; col < 4; ++col) { 438 a.setDouble(row, col, i); 439 b.setDouble(col, row, i++); 440 } 441 } 442 443 a.transpose(); 444 REPORTER_ASSERT(reporter, nearly_equal(a, b)); 445} 446 447static void test_get_set_double(skiatest::Reporter* reporter) { 448 SkMatrix44 a(SkMatrix44::kUninitialized_Constructor); 449 for (int row = 0; row < 4; ++row) { 450 for (int col = 0; col < 4; ++col) { 451 a.setDouble(row, col, 3.141592653589793); 452 REPORTER_ASSERT(reporter, 453 nearly_equal_double(3.141592653589793, 454 a.getDouble(row, col))); 455 a.setDouble(row, col, 0); 456 REPORTER_ASSERT(reporter, 457 nearly_equal_double(0, a.getDouble(row, col))); 458 } 459 } 460} 461 462static void test_set_row_col_major(skiatest::Reporter* reporter) { 463 SkMatrix44 a(SkMatrix44::kUninitialized_Constructor); 464 SkMatrix44 b(SkMatrix44::kUninitialized_Constructor); 465 466 for (int row = 0; row < 4; ++row) { 467 for (int col = 0; col < 4; ++col) { 468 a.setDouble(row, col, row * 4 + col); 469 } 470 } 471 472 double bufferd[16]; 473 float bufferf[16]; 474 a.asColMajord(bufferd); 475 b.setColMajord(bufferd); 476 REPORTER_ASSERT(reporter, nearly_equal(a, b)); 477 b.setRowMajord(bufferd); 478 b.transpose(); 479 REPORTER_ASSERT(reporter, nearly_equal(a, b)); 480 a.asColMajorf(bufferf); 481 b.setColMajorf(bufferf); 482 REPORTER_ASSERT(reporter, nearly_equal(a, b)); 483 b.setRowMajorf(bufferf); 484 b.transpose(); 485 REPORTER_ASSERT(reporter, nearly_equal(a, b)); 486} 487 488static void test_3x3_conversion(skiatest::Reporter* reporter) { 489 SkMScalar values4x4[16] = { 1, 2, 3, 4, 490 5, 6, 7, 8, 491 9, 10, 11, 12, 492 13, 14, 15, 16 }; 493 SkScalar values3x3[9] = { 1, 2, 4, 494 5, 6, 8, 495 13, 14, 16 }; 496 SkMScalar values4x4flattened[16] = { 1, 2, 0, 4, 497 5, 6, 0, 8, 498 0, 0, 1, 0, 499 13, 14, 0, 16 }; 500 SkMatrix44 a44(SkMatrix44::kUninitialized_Constructor); 501 a44.setRowMajor(values4x4); 502 503 SkMatrix a33 = a44; 504 SkMatrix expected33; 505 for (int i = 0; i < 9; i++) expected33[i] = values3x3[i]; 506 REPORTER_ASSERT(reporter, expected33 == a33); 507 508 SkMatrix44 a44flattened = a33; 509 SkMatrix44 expected44flattened(SkMatrix44::kUninitialized_Constructor); 510 expected44flattened.setRowMajor(values4x4flattened); 511 REPORTER_ASSERT(reporter, nearly_equal(a44flattened, expected44flattened)); 512 513 // Test that a point with a Z value of 0 is transformed the same way. 514 SkScalar vec4[4] = { 2, 4, 0, 8 }; 515 SkScalar vec3[3] = { 2, 4, 8 }; 516 517 SkScalar vec4transformed[4]; 518 SkScalar vec3transformed[3]; 519 SkScalar vec4transformed2[4]; 520 a44.mapScalars(vec4, vec4transformed); 521 a33.mapHomogeneousPoints(vec3transformed, vec3, 1); 522 a44flattened.mapScalars(vec4, vec4transformed2); 523 REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[0], vec3transformed[0])); 524 REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[1], vec3transformed[1])); 525 REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[3], vec3transformed[2])); 526 REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[0], vec4transformed2[0])); 527 REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[1], vec4transformed2[1])); 528 REPORTER_ASSERT(reporter, !nearly_equal_scalar(vec4transformed[2], vec4transformed2[2])); 529 REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[3], vec4transformed2[3])); 530} 531 532DEF_TEST(Matrix44, reporter) { 533 SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor); 534 SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor); 535 SkMatrix44 iden1(SkMatrix44::kUninitialized_Constructor); 536 SkMatrix44 iden2(SkMatrix44::kUninitialized_Constructor); 537 SkMatrix44 rot(SkMatrix44::kUninitialized_Constructor); 538 539 mat.setTranslate(1, 1, 1); 540 mat.invert(&inverse); 541 iden1.setConcat(mat, inverse); 542 REPORTER_ASSERT(reporter, is_identity(iden1)); 543 544 mat.setScale(2, 2, 2); 545 mat.invert(&inverse); 546 iden1.setConcat(mat, inverse); 547 REPORTER_ASSERT(reporter, is_identity(iden1)); 548 549 mat.setScale(SK_MScalar1/2, SK_MScalar1/2, SK_MScalar1/2); 550 mat.invert(&inverse); 551 iden1.setConcat(mat, inverse); 552 REPORTER_ASSERT(reporter, is_identity(iden1)); 553 554 mat.setScale(3, 3, 3); 555 rot.setRotateDegreesAbout(0, 0, -1, 90); 556 mat.postConcat(rot); 557 REPORTER_ASSERT(reporter, mat.invert(NULL)); 558 mat.invert(&inverse); 559 iden1.setConcat(mat, inverse); 560 REPORTER_ASSERT(reporter, is_identity(iden1)); 561 iden2.setConcat(inverse, mat); 562 REPORTER_ASSERT(reporter, is_identity(iden2)); 563 564 // test tiny-valued matrix inverse 565 mat.reset(); 566 mat.setScale(1.0e-12, 1.0e-12, 1.0e-12); 567 rot.setRotateDegreesAbout(0, 0, -1, 90); 568 mat.postConcat(rot); 569 mat.postTranslate(1.0e-12, 1.0e-12, 1.0e-12); 570 REPORTER_ASSERT(reporter, mat.invert(NULL)); 571 mat.invert(&inverse); 572 iden1.setConcat(mat, inverse); 573 REPORTER_ASSERT(reporter, is_identity(iden1)); 574 575 // test mixed-valued matrix inverse 576 mat.reset(); 577 mat.setScale(1.0e-10, 3.0, 1.0e+10); 578 rot.setRotateDegreesAbout(0, 0, -1, 90); 579 mat.postConcat(rot); 580 mat.postTranslate(1.0e+10, 3.0, 1.0e-10); 581 REPORTER_ASSERT(reporter, mat.invert(NULL)); 582 mat.invert(&inverse); 583 iden1.setConcat(mat, inverse); 584 REPORTER_ASSERT(reporter, is_identity(iden1)); 585 586 // test degenerate matrix 587 mat.reset(); 588 mat.set3x3(1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0); 589 REPORTER_ASSERT(reporter, !mat.invert(NULL)); 590 591 // test rol/col Major getters 592 { 593 mat.setTranslate(2, 3, 4); 594 float dataf[16]; 595 double datad[16]; 596 597 mat.asColMajorf(dataf); 598 assert16<float>(reporter, dataf, 599 1, 0, 0, 0, 600 0, 1, 0, 0, 601 0, 0, 1, 0, 602 2, 3, 4, 1); 603 mat.asColMajord(datad); 604 assert16<double>(reporter, datad, 1, 0, 0, 0, 605 0, 1, 0, 0, 606 0, 0, 1, 0, 607 2, 3, 4, 1); 608 mat.asRowMajorf(dataf); 609 assert16<float>(reporter, dataf, 1, 0, 0, 2, 610 0, 1, 0, 3, 611 0, 0, 1, 4, 612 0, 0, 0, 1); 613 mat.asRowMajord(datad); 614 assert16<double>(reporter, datad, 1, 0, 0, 2, 615 0, 1, 0, 3, 616 0, 0, 1, 4, 617 0, 0, 0, 1); 618 } 619 620 test_concat(reporter); 621 622 if (false) { // avoid bit rot, suppress warning (working on making this pass) 623 test_common_angles(reporter); 624 } 625 626 test_constructor(reporter); 627 test_gettype(reporter); 628 test_determinant(reporter); 629 test_invert(reporter); 630 test_transpose(reporter); 631 test_get_set_double(reporter); 632 test_set_row_col_major(reporter); 633 test_translate(reporter); 634 test_scale(reporter); 635 test_map2(reporter); 636 test_3x3_conversion(reporter); 637} 638