Files
gonum/spatial/r3/mat_safe.go

158 lines
3.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright ©2021 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build safe
// +build safe
// TODO(kortschak): Get rid of this rigmarole if https://golang.org/issue/50118
// is accepted.
package r3
import (
"gonum.org/v1/gonum/blas/blas64"
"gonum.org/v1/gonum/mat"
)
type array [9]float64
// At returns the value of a matrix element at row i, column j.
// At expects indices in the range [0,2].
// It will panic if i or j are out of bounds for the matrix.
func (m *Mat) At(i, j int) float64 {
if uint(i) > 2 {
panic(mat.ErrRowAccess)
}
if uint(j) > 2 {
panic(mat.ErrColAccess)
}
if m.data == nil {
m.data = new(array)
}
return m.data[i*3+j]
}
// Set sets the element at row i, column j to the value v.
func (m *Mat) Set(i, j int, v float64) {
if uint(i) > 2 {
panic(mat.ErrRowAccess)
}
if uint(j) > 2 {
panic(mat.ErrColAccess)
}
if m.data == nil {
m.data = new(array)
}
m.data[i*3+j] = v
}
// Eye returns the 3×3 Identity matrix
func Eye() *Mat {
return &Mat{&array{
1, 0, 0,
0, 1, 0,
0, 0, 1,
}}
}
// Skew returns the 3×3 skew symmetric matrix (right hand system) of v.
//
// ⎡ 0 -z y⎤
// Skew({x,y,z}) = ⎢ z 0 -x⎥
// ⎣-y x 0⎦
//
// Deprecated: use Mat.Skew()
func Skew(v Vec) (M *Mat) {
return &Mat{&array{
0, -v.Z, v.Y,
v.Z, 0, -v.X,
-v.Y, v.X, 0,
}}
}
// Mul takes the matrix product of a and b, placing the result in the receiver.
// If the number of columns in a does not equal 3, Mul will panic.
func (m *Mat) Mul(a, b mat.Matrix) {
ra, ca := a.Dims()
rb, cb := b.Dims()
switch {
case ra != 3:
panic(mat.ErrShape)
case cb != 3:
panic(mat.ErrShape)
case ca != rb:
panic(mat.ErrShape)
}
if m.data == nil {
m.data = new(array)
}
if ca != 3 {
// General matrix multiplication for the case where the inner dimension is not 3.
var t mat.Dense
t.Mul(a, b)
copy(m.data[:], t.RawMatrix().Data)
return
}
a00 := a.At(0, 0)
b00 := b.At(0, 0)
a01 := a.At(0, 1)
b01 := b.At(0, 1)
a02 := a.At(0, 2)
b02 := b.At(0, 2)
a10 := a.At(1, 0)
b10 := b.At(1, 0)
a11 := a.At(1, 1)
b11 := b.At(1, 1)
a12 := a.At(1, 2)
b12 := b.At(1, 2)
a20 := a.At(2, 0)
b20 := b.At(2, 0)
a21 := a.At(2, 1)
b21 := b.At(2, 1)
a22 := a.At(2, 2)
b22 := b.At(2, 2)
*(m.data) = array{
a00*b00 + a01*b10 + a02*b20, a00*b01 + a01*b11 + a02*b21, a00*b02 + a01*b12 + a02*b22,
a10*b00 + a11*b10 + a12*b20, a10*b01 + a11*b11 + a12*b21, a10*b02 + a11*b12 + a12*b22,
a20*b00 + a21*b10 + a22*b20, a20*b01 + a21*b11 + a22*b21, a20*b02 + a21*b12 + a22*b22,
}
}
// RawMatrix returns the blas representation of the matrix with the backing
// data of this matrix. Changes to the returned matrix will be reflected in
// the receiver.
func (m *Mat) RawMatrix() blas64.General {
if m.data == nil {
m.data = new(array)
}
return blas64.General{Rows: 3, Cols: 3, Data: m.data[:], Stride: 3}
}
func arrayFrom(vals []float64) *array {
return (*array)(vals)
}
// Mat returns a 3×3 rotation matrix corresponding to the receiver. It
// may be used to perform rotations on a 3-vector or to apply the rotation
// to a 3×n matrix of column vectors. If the receiver is not a unit
// quaternion, the returned matrix will not be a pure rotation.
func (r Rotation) Mat() *Mat {
w, i, j, k := r.Real, r.Imag, r.Jmag, r.Kmag
ii := 2 * i * i
jj := 2 * j * j
kk := 2 * k * k
wi := 2 * w * i
wj := 2 * w * j
wk := 2 * w * k
ij := 2 * i * j
jk := 2 * j * k
ki := 2 * k * i
return &Mat{&array{
1 - (jj + kk), ij - wk, ki + wj,
ij + wk, 1 - (ii + kk), jk - wi,
ki - wj, jk + wi, 1 - (ii + jj),
}}
}