quaternion-test.scm 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. (test-begin "quaternion")
  2. (import (kawa quaternions))
  3. (test-equal 0 (+ +i+j+k -i-j-k))
  4. (test-equal -1 (* +i +i))
  5. (test-equal -1 (* +j +j))
  6. (test-equal -1 (* +k +k))
  7. (test-equal -1 (* +i +j +k))
  8. (test-equal 1+i+j+k (+ 1 +i +j +k))
  9. (test-equal 1-i-j-k (- 1 +i +j +k))
  10. (test-equal 1 (/ 1+i+j+k 1+i+j+k))
  11. (test-equal +k (* (/ -i) +j))
  12. (test-equal -k (* +j (/ -i)))
  13. (test-eqv #t (quaternion? 0))
  14. (test-eqv #t (quaternion? -i))
  15. (test-eqv #t (quaternion? 1+2i-3j+4k))
  16. (test-eqv #f (quaternion? 10.0m))
  17. (test-eqv #f (quaternion? "x"))
  18. (test-eqv #t (quaternion? (java.lang.Double:valueOf 5.5)))
  19. (test-begin "real-part")
  20. (test-equal 0 (real-part 0))
  21. (test-equal 0 (real-part -i))
  22. (test-equal 1 (real-part 1+2i-3j+4k))
  23. (test-end "real-part")
  24. (test-begin "imag-part")
  25. (test-equal 0 (imag-part 0))
  26. (test-equal -1 (imag-part -i))
  27. (test-equal 2 (imag-part 1+2i-3j+4k))
  28. (test-end "imag-part")
  29. (test-begin "jmag-part")
  30. (test-equal 0 (jmag-part 0))
  31. (test-equal 0 (jmag-part -i))
  32. (test-equal -3 (jmag-part 1+2i-3j+4k))
  33. (test-end "jmag-part")
  34. (test-begin "kmag-part")
  35. (test-equal 0 (kmag-part 0))
  36. (test-equal 0 (kmag-part -i))
  37. (test-equal 4 (kmag-part 1+2i-3j+4k))
  38. (test-end "kmag-part")
  39. (test-begin "vector-part")
  40. (test-equal 0 (vector-part 0))
  41. (test-equal -i (vector-part -i))
  42. (test-equal +2i-3j+4k (vector-part 1+2i-3j+4k))
  43. (test-end "vector-part")
  44. (test-begin "unit-vector")
  45. (test-equal 0 (unit-vector 0))
  46. (test-equal -i (unit-vector -i))
  47. (test-equal (* (/ (sqrt 3)) +i+j+k) (unit-vector 3+3i+3j+3k))
  48. (test-equal 1.0 (magnitude (unit-vector 1+2i+3j+4k)))
  49. (test-end "unit-vector")
  50. (test-begin "vector-quaternion?")
  51. (test-eqv #t (vector-quaternion? 0))
  52. (test-eqv #t (vector-quaternion? +i+j+k))
  53. (test-eqv #f (vector-quaternion? 1-i))
  54. (test-end "vector-quaternion?")
  55. (test-begin "make-vector-quaternion")
  56. (test-equal +i+2j+3k (make-vector-quaternion 1 2 3))
  57. (test-end "make-vector-quaternion")
  58. (test-begin "vector-quaternion->list")
  59. (test-equal '(1 2 3) (vector-quaternion->list +i+2j+3k))
  60. (test-end "vector-quaternion->list")
  61. (test-begin "unit-quaternion")
  62. (test-equal 0 (unit-quaternion 0))
  63. (test-equal +i (unit-quaternion 0.0+0.00001i+0.0j+0.0k))
  64. (test-assert (= 1/2+1/2i+1/2j+1/2k (unit-quaternion 1+i+j+k)))
  65. (test-end "unit-quaternion")
  66. (test-begin "magnitude")
  67. (test-eqv 5.0 (magnitude 3+4i))
  68. (test-eqv 5.0 (magnitude 3-4j))
  69. (test-eqv 5.0 (magnitude 4+3k))
  70. (test-eqv 5.0 (magnitude +3i-4j))
  71. (test-eqv 5.0 (magnitude -4i+3k))
  72. (test-eqv 5.0 (magnitude -3j-4k))
  73. (test-eqv 5.0 (magnitude +5k))
  74. (test-end "magnitude")
  75. (test-begin "angle")
  76. (test-eqv 1.5 (angle 3@1.5))
  77. (test-eqv 1.5 (angle 3@1.5%0.2))
  78. (test-eqv 1.5 (angle 3@1.5&-0.4))
  79. (test-eqv 1.5 (angle 3@1.5%0.2&-0.4))
  80. (test-assert (= (/ java.lang.Math:PI 2) (angle +i)))
  81. (test-end "angle")
  82. (test-begin "colatitude")
  83. (test-eqv 0 (colatitude 3@1.5))
  84. (test-eqv 0.2 (colatitude 3@1.5%0.2))
  85. (test-eqv 0 (colatitude 3@1.5&-0.4))
  86. (test-eqv 0.2 (colatitude 3@1.5%0.2&-0.4))
  87. (test-end "colatitude")
  88. (test-begin "longitude")
  89. (test-eqv 0 (longitude 3@1.5))
  90. (test-eqv 0.0 (longitude 3@1.5%0.2))
  91. (test-eqv 0 (longitude 3@1.5&-0.4))
  92. (test-eqv -0.4 (longitude 3@1.5%0.2&-0.4))
  93. (test-end "longitude")
  94. (test-begin "make-rectangular")
  95. (test-equal 1+2i+3j+4k (make-rectangular 1 2 3 4))
  96. (test-equal 1.5-2i (make-rectangular 1.5 -2))
  97. (test-equal 1.5-2i (make-rectangular 1.5 -2 0 0))
  98. (test-end "make-rectangular")
  99. (test-begin "make-polar")
  100. (test-equal 1@1.5 (make-polar 1 1.5))
  101. (test-equal 1@1.5 (make-polar 1 1.5 0 0))
  102. (test-equal 1@1.5 (make-polar 1 1.5 0 0.3))
  103. (test-equal 1@1.5%-0.2 (make-polar 1 1.5 -0.2 0))
  104. (test-equal 1@1.5%-0.2&0.4 (make-polar 1 1.5 -0.2 0.4))
  105. (test-end "make-polar")
  106. (test-begin "dot-product")
  107. (test-error #t (dot-product 1+2i+3j+4k +i+j+k))
  108. (test-equal (- (real-part (* +i+j+k +2i-3j-4k))) (dot-product +i+j+k +2i-3j-4k))
  109. (test-equal -5 (dot-product +i+j+k +2i-3j-4k))
  110. (test-equal 0 (dot-product +i +j+k))
  111. (test-end "dot-product")
  112. (test-begin "cross-product")
  113. (test-equal +k (cross-product +i +j))
  114. (test-equal -3i+6j-3k (cross-product +i+2j+3k +4i+5j+6k))
  115. (test-equal 0 (cross-product -i-j-k +3i+3j+3k))
  116. (test-end "cross-product")
  117. (test-begin "conjugate")
  118. (test-equal 1-i (conjugate 1+i))
  119. (test-equal 1+2i-3j+4k (conjugate 1-2i+3j-4k))
  120. (test-end "conjugate")
  121. (test-begin "expt")
  122. (test-eqv #t (real-valued? (expt +i +i)))
  123. (test-equal (expt +i +i) (expt +j +j))
  124. (test-equal (expt +i +i) (expt +k +k))
  125. (test-assert (= (java.lang.Math:exp (/ (- java.lang.Math:PI) 2))
  126. (expt +i +i)))
  127. (test-end "expt")
  128. (test-begin "sqrt")
  129. (test-approximate (make-rectangular (/ (sqrt 2)) 0 0 (/ (sqrt 2)))
  130. (sqrt +k)
  131. 0.0000000001+0.0000000001i+0.0000000001j+0.0000000001k)
  132. (test-end "sqrt")
  133. (import (kawa rotations))
  134. (test-begin "rotation-matrix")
  135. (let* ((q 1/2+1/2i+1/2j+1/2k) ; 120 degrees about (1,1,1)
  136. (m1 (quaternion->rotation-matrix q))
  137. (m2 (quaternion->rotation-matrix (* q q))) ; 240 degrees
  138. (m3 (quaternion->rotation-matrix (* q q q)))) ; 360 degrees
  139. ;; for a 120-degree rotation about (1,1,1), +X->+Y, +Y->+Z, +Z->+X
  140. ;; m1 is #2a((0 0 1) (1 0 0) (0 1 0))
  141. (test-equal (double[] 0 1 0) (double[] (m1 0 0) (m1 1 0) (m1 2 0))) ; col 0
  142. (test-equal (double[] 0 0 1) (double[] (m1 0 1) (m1 1 1) (m1 2 1))) ; col 1
  143. (test-equal (double[] 1 0 0) (double[] (m1 0 2) (m1 1 2) (m1 2 2))) ; col 2
  144. ;; for 240 degrees, +X->+Z, +Y->+X, +Z->+Y
  145. (test-equal (double[] 0 0 1) (double[] (m2 0 0) (m2 1 0) (m2 2 0))) ; col 0
  146. (test-equal (double[] 1 0 0) (double[] (m2 0 1) (m2 1 1) (m2 2 1))) ; col 1
  147. (test-equal (double[] 0 1 0) (double[] (m2 0 2) (m2 1 2) (m2 2 2))) ; col 2
  148. ;; for 360 degrees, matrix is identity -- but we're on the other
  149. ;; side of the hypersphere: q^3 == -1
  150. (test-equal -1 (* q q q))
  151. (test-equal (double[] 1 0 0) (double[] (m3 0 0) (m3 1 0) (m3 2 0))) ; col 0
  152. (test-equal (double[] 0 1 0) (double[] (m3 0 1) (m3 1 1) (m3 2 1))) ; col 1
  153. (test-equal (double[] 0 0 1) (double[] (m3 0 2) (m3 1 2) (m3 2 2)))) ; col 2
  154. (test-end "rotation-matrix")
  155. (test-begin "rotation-axis/angle")
  156. (test-equal +i (rotation-axis (rotx 0.2)))
  157. (test-equal +i (rotation-axis 1))
  158. (test-equal 0.0 (rotation-angle 1))
  159. (test-approximate 0.2 (rotation-angle (rotx 0.2)) 0.0000000001)
  160. (test-approximate (rotx 0.2) (make-axis/angle 1 0 0 0.2) 0.0000000001+0.0000000001i)
  161. (test-approximate (roty 0.3) (make-axis/angle 0 1 0 0.3) 0.0000000001+0.0000000001j)
  162. (test-approximate (rotz 0.4) (make-axis/angle 0 0 1 0.4) 0.0000000001+0.0000000001k)
  163. (test-end "rotation-axis/angle")
  164. (test-begin "angle-sets")
  165. (for-each
  166. (lambda (f)
  167. (test-equal 1 (f 0 0 0)))
  168. (list
  169. make-intrinsic-xyx make-intrinsic-xzx make-intrinsic-yxy
  170. make-intrinsic-yzy make-intrinsic-zxz make-intrinsic-zyz
  171. make-intrinsic-xyz make-intrinsic-xzy make-intrinsic-yxz
  172. make-intrinsic-yzx make-intrinsic-zxy make-intrinsic-zyx
  173. make-extrinsic-xyx make-extrinsic-xyz make-extrinsic-xzx
  174. make-extrinsic-xzy make-extrinsic-yxy make-extrinsic-yxz
  175. make-extrinsic-yzx make-extrinsic-yzy make-extrinsic-zxy
  176. make-extrinsic-zxz make-extrinsic-zyx make-extrinsic-zyz))
  177. (let-values (((a b c) (rpy (make-rpy 0.1 -0.2 0.4))))
  178. (test-approximate 0.1 a 0.0000000001)
  179. (test-approximate -0.2 b 0.0000000001)
  180. (test-approximate 0.4 c 0.0000000001))
  181. (test-approximate (make-euler-xyx 0.1 0.2 0.3)
  182. (make-extrinsic-xyx 0.3 0.2 0.1)
  183. 0.0000000001+0.0000000001i+0.0000000001j+0.0000000001k)
  184. (test-approximate (make-tait-bryan-yxz 0.1 0.2 0.3)
  185. (make-extrinsic-zxy 0.3 0.2 0.1)
  186. 0.0000000001+0.0000000001i+0.0000000001j+0.0000000001k)
  187. (for-each
  188. (lambda (f g)
  189. (let-values (((a b c) (f (g 1 0 2))))
  190. (test-approximate 0 a 1e-10)
  191. (test-approximate 0 b 1e-10)
  192. (test-approximate 3 c 1e-10)))
  193. (list euler-xyx euler-xzx euler-yxy euler-yzy euler-zxz euler-zyz)
  194. (list make-euler-xyx make-euler-xzx make-euler-yxy make-euler-yzy
  195. make-euler-zxz make-euler-zyz))
  196. (test-end "angle-sets")
  197. (test-begin "rotate-vector")
  198. (let ((r (make-rotation-procedure 1/2+1/2i+1/2j+1/2k))
  199. (eps 0.0000000001+0.0000000001i+0.0000000001j+0.0000000001k))
  200. (test-approximate +j (r +i) eps)
  201. (test-approximate +k (r +j) eps)
  202. (test-approximate +i (r +k) eps)
  203. (test-approximate +j (rotate-vector (rotz (java.lang.Math:toRadians 90)) +i) eps)
  204. (let* ((a -0.105)
  205. (q (make-axis/angle +j a))
  206. (v (rotate-vector q (make-vector-quaternion 0 0 1))))
  207. (test-approximate (cos a) (imag-part v) eps)
  208. (test-equal 0.0 (jmag-part v))
  209. (test-approximate (sin a) (kmag-part v) eps)))
  210. (test-end "rotate-vector")
  211. (test-end)