夏が来れば思い出す、Euler角、四元数(2): Scalaで実装してみた。

By | 2018年7月16日 , Last update: 2022年8月7日

はじめに

ちょっと前に書いた記事で四元数の乗算を用いて三次元空間における回転変換を表現できることを示しました。

この記事ではそれを受ける形で、四元数の演算を行うScalaのオブジェクト及びコンパニオンクラスを実装していきます。

スポンサーリンク

実装の方針。

実装のやり方についてもかなり前の記事で書いた複素数のオブジェクト及びコンパニオンクラスに準ずることにします。

実装例。

実装例は以下のような感じになります。割と長いです。

package info.pandanote.test
import scala.reflect.ClassTag
import scala.math._
// A class to represent and to handle a quaternion.
// 四元数を扱うためのクラスを書いてみました。
case class Quaternion(real: Double, _i: Double, _j: Double, _k: Double) {
override def toString(): String = real + (if (_i == 0.0) "" else ((if (_i>0.0)"+"else"-")+(if (_i>0.0)_i else -_i) + "i")) + (if (_j == 0.0) "" else ((if (_j>0.0)"+"else"-")+(if (_j>0.0)_j else -_j) + "j")) + (if (_k == 0.0) "" else ((if (_k>0.0)"+"else"-")+(if (_k>0.0)_k else -_k) + "k"))
def re() = real
def i() = _i
def j() = _j
def k() = _k
def +(that: Quaternion) = Quaternion(this.real+that.real,this._i+that._i,this._j+that._j,this._k+that._k)
def +(that: Int) = Quaternion(this.real+that,this._i,this._j,this._k)
def +(that: Long) = Quaternion(this.real+that,this._i,this._j,this._k)
def +(that: Float) = Quaternion(this.real+that,this._i,this._j,this._k)
def +(that: Double) = Quaternion(this.real+that,this._i,this._j,this._k)
def -(that: Quaternion) = Quaternion(this.real-that.real,this._i-that._i,this._j-that._j,this._k-that._k)
def -(that: Int) = Quaternion(this.real-that,this._i,this._j,this._k)
def -(that: Long) = Quaternion(this.real-that,this._i,this._j,this._k)
def -(that: Float) = Quaternion(this.real-that,this._i,this._j,this._k)
def -(that: Double) = Quaternion(this.real-that,this._i,this._j,this._k)
def *(that: Quaternion)
= Quaternion(this.real*that.real-this._i*that._i-this._j*that._j-this._k*that._k,
this.real*that._i+this._i*that.real+this._j*that._k-this._k*that._j,
this.real*that._j-this._i*that._k+this._j*that.real+this._k*that._i,
this.real*that._k+this._i*that._j-this._j*that._i+this._k*that.real)
def *(that: Int) = Quaternion(this.real*that,this._i*that,this._j*that,this._k*that)
def *(that: Long) = Quaternion(this.real*that,this._i*that,this._j*that,this._k*that)
def *(that: Float) = Quaternion(this.real*that,this._i*that,this._j*that,this._k*that)
def *(that: Double) = Quaternion(this.real*that,this._i*that,this._j*that,this._k*that)
def unary_- = Quaternion(-this.real,-this._i,-this._j,-this._k)
def abs = math.sqrt(this.real*this.real+this._i*this._i+this._j*this._j+this._k*this._k)
def conjugate = Quaternion(this.real,-this._i,-this._j,-this._k)
// 除算: 四元数を除数とする除算は、逆数を右からかける演算として定義します。
def /(that: Int) = Quaternion(this.real/that,this._i/that,this._j/that,this._k/that)
def /(that: Long) = Quaternion(this.real/that,this._i/that,this._j/that,this._k/that)
def /(that: Float) = Quaternion(this.real/that,this._i/that,this._j/that,this._k/that)
def /(that: Double) = Quaternion(this.real/that,this._i/that,this._j/that,this._k/that)
def /(that: Quaternion) = {
val xnorm = that.real*that.real+that._i*that._i+that._j*that._j+that._k*that._k
val q = this*that.conjugate
Quaternion(q.real/xnorm,q._i/xnorm,q._j/xnorm,q._k/xnorm)
}
// 四元数の剰余計算というものが定義されているのかどうかわかりませんが、書いてみました。
// 複素数と同様の考え方で定義しています。
def %(that: Quaternion) = {
val div = this./(that)
this - Quaternion(Math.round(div.real),Math.round(div.i),Math.round(div.j),Math.round(div.k))*that
}
def %(that: Int): Quaternion = this.%(Quaternion(that, 0, 0, 0))
def %(that: Long): Quaternion = %(Quaternion(that, 0, 0, 0))
def %(that: Float): Quaternion = %(Quaternion(that, 0, 0, 0))
def %(that: Double): Quaternion = %(Quaternion(that, 0, 0, 0))
def exp = {
val expreal = math.exp(real)
val vlen = math.sqrt(_i*_i+_j*_j+_k*_k)
Quaternion(math.cos(vlen),math.sin(vlen)*_i/vlen,math.sin(vlen)*_j/vlen,math.sin(vlen)*_k/vlen)*expreal
}
def log = {
val logimag = math.acos(real/abs)/math.sqrt(_i*_i+_j*_j+_k*_k)
Quaternion(math.log(abs),_i*logimag,_j*logimag,_k*logimag)
}
def pow(that: Int): Quaternion = pow(Quaternion(that,0,0,0))
def pow(that: Double): Quaternion = pow(Quaternion(that,0,0,0))
def pow(that: Quaternion): Quaternion = {
if (that == Quaternion.zero) Quaternion.one
else if (this == Quaternion.zero) {
// 実数成分は正である場合に限り0を返す。
if (that.real < 0.0 || that._i != 0.0 || that._j != 0.0 || that._k != 0.0) Quaternion.nan
else Quaternion.zero
} else {
Quaternion.exp(log*that)
}
}
// こんなのも定義してみます。
def **(that: Quaternion): Quaternion = pow(that)
def **(that: Double): Quaternion = pow(that)
def **(that: Int): Quaternion = pow(that)
override def equals(that: Any) = that match {
case that: Quaternion => this.real == that.real && this._i == that._i && this._j == that._j && this._k == that._k
case real: Double => this.real == real && this._i == 0 && this._j == 0 && this._k == 0
case real: Int => this.real == real && this._i == 0 && this._j == 0 && this._k == 0
case real: Short => this.real == real && this._i == 0 && this._j == 0 && this._k == 0
case real: Long => this.real == real && this._i == 0 && this._j == 0 && this._k == 0
case real: Float => this.real == real && this._i == 0 && this._j == 0 && this._k == 0
case _ => false
}
// 試しにこんな演算子を定義してみます。
def <>(that: Quaternion) =
(this.real != that.real || this._i != that._i || this._j != that._j || this._k != that._k)
override def hashCode() = real.## ^ _i.## ^ _j.## ^ _k.##
}
object Quaternion {
outer =>
val one = new Quaternion(1,0,0,0)
val zero = new Quaternion(0,0,0,0)
val nan = new Quaternion(Double.NaN,Double.NaN,Double.NaN,Double.NaN)
// Javaでいうところのstaticなメソッドみたいなものです。
def exp(that: Quaternion): Quaternion = that.exp
def log(that: Quaternion): Quaternion = that.log
// 実数に四元数を作用させる演算が定義されていなかったので、追加しました。
// 試行錯誤の末、以下の一行になりました…
implicit def fromDouble(d: Double) = new Quaternion(d,0,0,0)
}

考慮が必要と思われる点(その1): 除算

四元数を除数とする除算は、逆数を右からかける演算として以下の式で定義します。

(1)

なお、四元数の集合の任意の2元の間には乗法に関する交換則が成立しないため、逆数を左からのようにかける演算も除算と考えることができそうですが、上記のコードではこれに対応する実装を行っていません。

考慮が必要と思われる点(その2): 剰余

四元数の剰余というものが定義できるかどうかわかりませんが、複素数の場合と同様に以下の手順で計算し、その結果得られた数を剰余とするコードを実装しています。

  1. 剰余演算子の左辺の四元数(と置きます。)を被除数、剰余演算子の右辺の四元数(と置きます。)を除数とする除算を実行し、その商を得ます。以下、商の値をと置きます。
  2. の実部及び虚部()成分をそれぞれ四捨五入した値を求め、これをとします。
  3. 以下の式により計算される値を剰余とします。除算をと定義しているため、に対してを左からかけています。
    (2)

考慮が必要と思われる点(その3): 四元数のべき乗

としたときに四元数のべき乗を以下の式で計算しています。

(3)

テスト。

とりあえず、Eclipseで実行できるようにmainメソッド入りのテスト用オブジェクト(QuaternionTestオブジェクト)を書いてみました。以下のような感じになります。

package info.pandanote.test
import Quaternion._
object QuaternionTest {
def main(args: Array[String]): Unit = {
val a = Quaternion(-2,4,-3,3)
val b = Quaternion(-3,3,5,0)
val c = Quaternion(5,0,9,-4)
val d = Quaternion(9,-4,4,-1)
val e = Quaternion(4,-1,-2,4)
val f = -3.000428692900978
val g = 10
val aa = Quaternion(2,1,3,-3)
val ab = Quaternion(3,-3,4,5)
val ac = Quaternion(4,5,2,1)
val ad = Quaternion.one
// toString()
println("--- toString() ---")
println("a="+a.toString)
println("b="+b.toString)
println("c="+c.toString)
println("d="+d.toString)
println("e="+e.toString)
println("aa="+aa.toString)
println("ab="+ab.toString)
println("ac="+ac.toString)
println("ad="+ad.toString)
println(Quaternion.one)
println(Quaternion.zero)
// re()
println("--- re() ---")
println("Re(a) = "+a.re.toString)
println("Re(b) = "+b.re.toString)
println("Re(c) = "+c.re.toString)
println("Re(d) = "+d.re.toString)
println("Re(e) = "+e.re.toString)
println("Re(aa) = "+aa.re.toString)
println("Re(ab) = "+ab.re.toString)
println("Re(ac) = "+ac.re.toString)
println("Re(ad) = "+ad.re.toString)
println("Re(Quaternion.one) = "+Quaternion.one.re.toString)
// i()
println("--- i() ---")
println("a.i = "+a.i.toString)
println("b.i = "+b.i.toString)
println("c.i = "+c.i.toString)
println("d.i = "+d.i.toString)
println("e.i = "+e.i.toString)
println("aa.i = "+aa.i.toString)
println("ab.i = "+ab.i.toString)
println("ac.i = "+ac.i.toString)
println("ad.i = "+ad.i.toString)
// j()
println("--- j() ---")
println("a.j = "+a.j.toString)
println("b.j = "+b.j.toString)
println("c.j = "+c.j.toString)
println("d.j = "+d.j.toString)
println("e.j = "+e.j.toString)
println("aa.j = "+aa.j.toString)
println("ab.j = "+ab.j.toString)
println("ac.j = "+ac.j.toString)
println("ad.j = "+ad.j.toString)
// k()
println("--- k() ---")
println("a.k = "+a.k.toString)
println("b.k = "+b.k.toString)
println("c.k = "+c.k.toString)
println("d.k = "+d.k.toString)
println("e.k = "+e.k.toString)
println("aa.k = "+aa.k.toString)
println("ab.k = "+ab.k.toString)
println("ac.k = "+ac.k.toString)
println("ad.k = "+ad.k.toString)
// +(that: Quaternion)
println("--- +(that: Quaternion) ---")
println("a + b = "+(a + b).toString)
println("b + c = "+(b + c).toString)
println("c + d = "+(c + d).toString)
println("d + e = "+(d + e).toString)
println("aa + 1 = "+(aa+Quaternion.one).toString)
// +(that: Int)
println("--- +(that: Int) ---")
println("a + 2 = "+(a + 2).toString)
println("b + 3 = "+(b + 3).toString)
println("c + 4 = "+(c + 4).toString)
println("d + 5 = "+(d + 5).toString)
println("e + 6 = "+(d + 6).toString)
// +(that: Long)
println("--- +(that: Long) ---")
println("a + 2L = "+(a + 2L).toString)
println("b + 4L = "+(b + 4L).toString)
println("c + 8L = "+(c + 8L).toString)
println("d + 16L = "+(d + 16L).toString)
println("e + 32L = "+(e + 32L).toString)
// +(that: Float)
println("--- +(that: Float) ---")
println("a + 0.1f = "+(a + 0.1f).toString)
println("b + 0.2f = "+(b + 0.2f).toString)
println("c + 0.3f = "+(c + 0.3f).toString)
println("d + 0.4f = "+(d + 0.4f).toString)
println("e + 0.5f = "+(e + 0.5f).toString)
// +(that: Double)
println("--- +(that: Double) ---")
println("a + 0.3 = "+(a + 0.3).toString)
println("b + 0.6 = "+(b + 0.6).toString)
println("c + 0.9 = "+(c + 0.9).toString)
println("d + 1.2 = "+(d + 1.2).toString)
println("e + 1.5 = "+(e + 1.5).toString)
// -(that: Quaternion)
println("--- -(that: Quaternion) ---")
println("a - b = "+(a - b).toString)
println("b - c = "+(b - c).toString)
println("c - d = "+(c - d).toString)
println("d - e = "+(d - e).toString)
println("aa - ab = "+(aa - ab).toString)
// -(that: Int)
println("--- -(that: Int) ---")
println("a - 2 = "+(a - 2).toString)
println("b - 3 = "+(b - 3).toString)
println("c - 4 = "+(c - 4).toString)
println("d - 5 = "+(d - 5).toString)
println("e - 6 = "+(e - 6).toString)
// -(that: Long)
println("--- -(that: Long) ---")
println("a - 1L = "+(a - 1L).toString)
println("b - 2L = "+(b - 2L).toString)
println("c - 4L = "+(c - 4L).toString)
println("d - 8L = "+(d - 8L).toString)
println("e - 16L = "+(e - 16L).toString)
// -(that: Float)
println("--- -(that: Float) ---")
println("a - 0.1f = "+(a - 0.1f).toString)
println("b - 0.2f = "+(b - 0.2f).toString)
println("c - 0.3f = "+(c - 0.3f).toString)
println("d - 0.4f = "+(d - 0.4f).toString)
println("e - 0.5f = "+(e - 0.5f).toString)
// -(that: Double)
println("--- -(that: Double) ---")
println("a - 0.3 = "+(a - 0.3).toString)
println("b - 0.6 = "+(b - 0.6).toString)
println("c - 0.9 = "+(c - 0.9).toString)
println("d - 1.2 = "+(d - 1.2).toString)
println("e - 1.5 = "+(e - 1.5).toString)
// *(that: Quaternion)
println("--- *(that: Quaternion) ---")
println("a * b = "+(a * b).toString)
println("b * c = "+(b * c).toString)
println("c * d = "+(c * d).toString)
println("d * e = "+(d * e).toString)
println("aa * ac = "+(aa*ac).toString)
// *(that: Int)
println("--- *(that: Int) ---")
println("a * 2 = "+(a * 2).toString)
println("b * 3 = "+(b * 3).toString)
println("c * 4 = "+(c * 4).toString)
println("d * 5 = "+(d * 5).toString)
println("e * 6 = "+(e * 6).toString)
// *(that: Long)
println("--- *(that: Long) ---")
println("a * 7L = "+(a * 7L).toString)
println("b * 8L = "+(b * 8L).toString)
println("c * 9L = "+(c * 9L).toString)
println("d * 10L = "+(d * 10L).toString)
println("e * 11L = "+(e * 11L).toString)
// *(that: Float)
println("--- *(that: Float) ---")
println("a * 0.2f = "+(a * 0.2f).toString)
println("b * 0.3f = "+(b * 0.3f).toString)
println("c * 0.4f = "+(c * 0.4f).toString)
println("d * 0.5f = "+(d * 0.5f).toString)
println("e * 0.6f = "+(e * 0.6f).toString)
// *(that: Double)
println("--- *(that: Double) ---")
println("a * 0.2 = "+(a * 0.2).toString)
println("b * 0.3 = "+(b * 0.3).toString)
println("c * 0.4 = "+(c * 0.4).toString)
println("d * 0.5 = "+(d * 0.5).toString)
println("e * 0.6 = "+(e * 0.6).toString)
// /(that: Quaternion)
println("--- /(that: Quaternion) ---")
println("a / b = "+(a / b).toString)
println("b / c = "+(b / c).toString)
println("c / d = "+(c / d).toString)
println("d / e = "+(d / e).toString)
println("aa / ab = "+(aa/ab).toString)
// /(that: Int)
println("--- /(that: Int) ---")
println("a / 2 = "+(a / 2).toString)
println("b / 3 = "+(b / 3).toString)
println("c / 4 = "+(c / 4).toString)
println("d / 5 = "+(d / 5).toString)
println("e / 6 = "+(e / 6).toString)
println("ab / 4 = "+(ab / 4).toString)
// /(that: Long)
println("--- /(that: Long) ---")
println("a / 6L = "+(a / 6L).toString)
println("b / 5L = "+(b / 5L).toString)
println("c / 4L = "+(c / 4L).toString)
println("d / 3L = "+(d / 3L).toString)
println("e / 2L = "+(e / 2L).toString)
// /(that: Float)
println("--- /(that: Float) ---")
println("a / 0.5f = "+(a / 0.5f).toString)
println("b / 0.6f = "+(b / 0.6f).toString)
println("c / 0.7f = "+(c / 0.7f).toString)
println("d / 0.8f = "+(d / 0.8f).toString)
println("e / 0.9f = "+(e / 0.9f).toString)
// /(that: Double)
println("--- /(that: Double) ---")
println("a / 1.1 = "+(a / 1.1).toString)
println("b / 1.2 = "+(b / 1.2).toString)
println("c / 1.3 = "+(c / 1.3).toString)
println("d / 1.4 = "+(d / 1.4).toString)
println("e / 1.5 = "+(e / 1.5).toString)
// %(that: Quaternion)
println("--- %(that: Quaternion) ---")
println("a % b = "+(a % b).toString)
println("b % c = "+(b % c).toString)
println("c % d = "+(c % d).toString)
println("d % e = "+(d % e).toString)
// %(that: Int)
println("--- %(that: Int) ---")
println("a % 5 = "+(a % 5).toString)
println("b % 6 = "+(b % 6).toString)
println("c % 7 = "+(c % 7).toString)
println("d % 8 = "+(d % 8).toString)
println("ab % 4 = "+(ab % 4).toString)
// %(that: Long)
println("--- %(that: Long) ---")
println("a % 5L = "+(a % 5L).toString)
println("b % 6L = "+(b % 6L).toString)
println("c % 7L = "+(c % 7L).toString)
println("d % 8L = "+(d % 8L).toString)
println("e % 4L = "+(e % 9L).toString)
// %(that: Float)
println("--- %(that: Float) ---")
println("a % 1.5f = "+(a % 1.5f).toString)
println("b % 2.0f = "+(b % 2.0f).toString)
println("c % 2.5f = "+(c % 2.5f).toString)
println("d % 3.0f = "+(d % 3.0f).toString)
println("e % 4.0f = "+(e % 4.0f).toString)
// %(that: Double)
println("--- %(that: Double) ---")
println("a % 1.5 = "+(a % 1.5).toString)
println("b % 2.0 = "+(b % 2.0).toString)
println("c % 2.5 = "+(c % 2.5).toString)
println("d % 3.0 = "+(d % 3.0).toString)
println("e % 4.0 = "+(d % 4.0).toString)
// unary_- = Quaternion(-real,-imag,this.imagUnit)
println("--- unary_- ---")
println("-a = "+(-a).toString)
println("-b = "+(-b).toString)
println("-c = "+(-c).toString)
println("-d = "+(-d).toString)
println("-e = "+(-e).toString)
// abs = math.sqrt(real*real+imag*imag)
println("--- abs ---")
println("a.abs = "+a.abs.toString)
println("b.abs = "+b.abs.toString)
println("c.abs = "+c.abs.toString)
println("d.abs = "+d.abs.toString)
println("e.abs = "+e.abs.toString)
// conjugate = Quaternion(real,-imag,this.imagUnit)
println("--- conjugate ---")
println("a.conjugate = "+a.conjugate.toString)
println("b.conjugate = "+b.conjugate.toString)
println("c.conjugate = "+c.conjugate.toString)
println("d.conjugate = "+d.conjugate.toString)
println("e.conjugate = "+e.conjugate.toString)
println("aa.conjugate*(ac-Quaternion.one*7) = "+(aa.conjugate*(ac-Quaternion.one*7)).toString)
// log = Quaternion(math.log(abs))
println("--- log ---")
println("a.log = "+a.log.toString)
println("b.log = "+b.log.toString)
println("c.log = "+c.log.toString)
println("d.log = "+d.log.toString)
println("e.log = "+e.log.toString)
// exp = {
println("--- exp ---")
println("a.exp = "+a.exp.toString)
println("b.exp = "+b.exp.toString)
println("c.exp = "+c.exp.toString)
println("d.exp = "+d.exp.toString)
println("e.exp = "+e.exp.toString)
println("aa.exp = "+aa.exp.toString)
println("aa.exp.log = "+aa.exp.log.toString)
println("aa.exp.log != aa: "+(aa.exp.log == aa))
// pow(that: Double)
println("--- pow(that: Double) ---")
println("a pow 0.2 = "+(a pow 0.2).toString)
println("b pow 0.4 = "+(b pow 0.4).toString)
println("c pow 0.6 = "+(c pow 0.6).toString)
println("d pow 0.8 = "+(d pow 0.8).toString)
println("e pow 1.1 = "+(e pow 1.1).toString)
println("a.pow(0.2) = "+a.pow(0.2).toString)
println("b.pow(0.4) = "+b.pow(0.4).toString)
println("c.pow(0.6) = "+c.pow(0.6).toString)
println("d.pow(0.8) = "+d.pow(0.8).toString)
println("e.pow(1.1) = "+e.pow(1.1).toString)
// pow(that: Int)
println("--- pow(that: Int) ---")
println("aa.pow(3) = "+aa.pow(3).toString)
// pow(that: Quaternion)
println("--- pow(that: Quaternion) ---")
println("a pow b = "+(a pow b).toString)
println("b pow c = "+(b pow c).toString)
println("c pow d = "+(c pow d).toString)
println("d pow e = "+(d pow e).toString)
println("e pow a = "+(e pow a).toString)
println("a.pow(b) = "+a.pow(b).toString)
println("b.pow(c) = "+b.pow(c).toString)
println("c.pow(d) = "+c.pow(d).toString)
println("d.pow(e) = "+d.pow(e).toString)
println("e.pow(a) = "+e.pow(a).toString)
println("aa.pow(aa) = "+aa.pow(aa).toString)
// **(that: Quaternion)
println("--- **(that: Quaternion) ---")
println("a ** b = "+(a ** b).toString)
println("b ** c = "+(b ** c).toString)
println("c ** d = "+(c ** d).toString)
println("d ** e = "+(d ** e).toString)
println("e ** a = "+(d ** e).toString)
println("aa ** ab = "+(aa**ab).toString)
// **(that: Double)
println("--- **(that: Double) ---")
println("a ** 0.2 = "+(a ** 0.2).toString)
println("b ** 0.4 = "+(b ** 0.4).toString)
println("c ** 0.6 = "+(c ** 0.6).toString)
println("d ** 0.8 = "+(d ** 0.8).toString)
println("e ** 1.1 = "+(e ** 1.1).toString)
// **(that: Int)
println("--- **(that: Int) ---")
println("aa ** 2 = "+(aa ** 2).toString)
// equals(that: Any)
println("--- equals(that: Any) ---")
println("a equals b: "+(a equals b).toString)
println("b equals c: "+(b equals c).toString)
println("c equals d: "+(c equals d).toString)
println("d equals e: "+(d equals e).toString)
println("e equals a: "+(e equals a).toString)
println("a equals a: "+(a equals a).toString)
println("b equals b: "+(b equals b).toString)
println("c equals c: "+(c equals c).toString)
println("d equals d: "+(d equals d).toString)
println("e equals e: "+(e equals e).toString)
println("ad == 1: "+(ad == 1).toString)
println("ad.equals(1): "+ad.equals(1))
println("aa != aa: "+(aa!=aa))
// <>(that: Quaternion)
println("--- <>(that: Quaternion) ---")
println("a <> b: "+(a <> b).toString)
println("b <> c: "+(b <> c).toString)
println("c <> d: "+(c <> d).toString)
println("d <> e: "+(d <> e).toString)
println("aa <> aa: "+(aa<>aa).toString)
// exp(that: Quaternion)
println("--- Quaternion.exp(that: Quaternion)---")
println("Quaternion.exp(a) = "+Quaternion.exp(a).toString)
println("Quaternion.exp(b) = "+Quaternion.exp(b).toString)
println("Quaternion.exp(c) = "+Quaternion.exp(c).toString)
println("Quaternion.exp(d) = "+Quaternion.exp(d).toString)
println("Quaternion.exp(e) = "+Quaternion.exp(e).toString)
println("Quaternion.exp(aa) = "+Quaternion.exp(aa).toString)
// log(that: Quaternion)
println("--- Quaternion.log(that: Quaternion)---")
println("Quaternion.log(a) = "+Quaternion.log(a).toString)
println("Quaternion.log(b) = "+Quaternion.log(b).toString)
println("Quaternion.log(c) = "+Quaternion.log(c).toString)
println("Quaternion.log(d) = "+Quaternion.log(d).toString)
println("Quaternion.log(e) = "+Quaternion.log(e).toString)
// Imaginary Unit and others.
println("--- Imaginary Unit and others. ---")
val aj = new Quaternion(2,-5,-1,6)
println("aj = "+aj)
println("aj * aa = "+(aj*aa).toString)
println("aa * aj = "+(aa*aj).toString)
println("aj.pow(0) = "+aj.pow(0))
println("aj.pow(2) = "+aj.pow(2))
println("aj * aj = "+(aj*aj))
println("aj.pow(2).log = "+aj.pow(2).log)
println("aj.pow(2).pow(0.5) = "+aj.pow(2).pow(0.5))
// -- Doubleクラスにメソッドを追加してみた。--
println("Append some methods to handle Quaternion")
println("g*a = "+(g*a).toString)
println("g/a = "+(g/a).toString)
println("g+a = "+(g+a).toString)
val g1: Double = 1
val g2: Double = 1
println("g1 equals g2: "+(g1 equals g2).toString)
}
}

テスト結果は長くなりますので掲載しないことにしますが、結果を確認した感じでは問題なさそうな感じに見えます。

まとめ

ここまで、Scalaで四元数を扱うためのオブジェクト及びクラスの実装について書きました。

前項で示したテスト用のプログラムもScalaTestで使用できるように書くべきところかもしれませんが、今回はここで力尽きてしまったので、別の機会に書きたいと考えています。

(´・ω・`)

この記事は以上です。

参考文献