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