gonum.org/v1/gonum@v0.14.0/spatial/r3/mat_unsafe.go (about) 1 // Copyright ©2021 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build !safe 6 // +build !safe 7 8 package r3 9 10 import ( 11 "unsafe" 12 13 "gonum.org/v1/gonum/blas/blas64" 14 "gonum.org/v1/gonum/mat" 15 ) 16 17 type array [3][3]float64 18 19 // At returns the value of a matrix element at row i, column j. 20 // At expects indices in the range [0,2]. 21 // It will panic if i or j are out of bounds for the matrix. 22 func (m *Mat) At(i, j int) float64 { 23 if m.data == nil { 24 m.data = new(array) 25 } 26 return m.data[i][j] 27 } 28 29 // Set sets the element at row i, column j to the value v. 30 func (m *Mat) Set(i, j int, v float64) { 31 if m.data == nil { 32 m.data = new(array) 33 } 34 m.data[i][j] = v 35 } 36 37 // Eye returns the 3×3 Identity matrix 38 func Eye() *Mat { 39 return &Mat{&array{ 40 {1, 0, 0}, 41 {0, 1, 0}, 42 {0, 0, 1}, 43 }} 44 } 45 46 // Skew returns the 3×3 skew symmetric matrix (right hand system) of v. 47 // 48 // ⎡ 0 -z y⎤ 49 // Skew({x,y,z}) = ⎢ z 0 -x⎥ 50 // ⎣-y x 0⎦ 51 // 52 // Deprecated: use Mat.Skew() 53 func Skew(v Vec) (M *Mat) { 54 return &Mat{&array{ 55 {0, -v.Z, v.Y}, 56 {v.Z, 0, -v.X}, 57 {-v.Y, v.X, 0}, 58 }} 59 } 60 61 // Mul takes the matrix product of a and b, placing the result in the receiver. 62 // If the number of columns in a does not equal 3, Mul will panic. 63 func (m *Mat) Mul(a, b mat.Matrix) { 64 ra, ca := a.Dims() 65 rb, cb := b.Dims() 66 switch { 67 case ra != 3: 68 panic(mat.ErrShape) 69 case cb != 3: 70 panic(mat.ErrShape) 71 case ca != rb: 72 panic(mat.ErrShape) 73 } 74 if m.data == nil { 75 m.data = new(array) 76 } 77 if ca != 3 { 78 // General matrix multiplication for the case where the inner dimension is not 3. 79 t := mat.NewDense(3, 3, m.slice()) 80 t.Mul(a, b) 81 return 82 } 83 84 a00 := a.At(0, 0) 85 b00 := b.At(0, 0) 86 a01 := a.At(0, 1) 87 b01 := b.At(0, 1) 88 a02 := a.At(0, 2) 89 b02 := b.At(0, 2) 90 a10 := a.At(1, 0) 91 b10 := b.At(1, 0) 92 a11 := a.At(1, 1) 93 b11 := b.At(1, 1) 94 a12 := a.At(1, 2) 95 b12 := b.At(1, 2) 96 a20 := a.At(2, 0) 97 b20 := b.At(2, 0) 98 a21 := a.At(2, 1) 99 b21 := b.At(2, 1) 100 a22 := a.At(2, 2) 101 b22 := b.At(2, 2) 102 m.data[0][0] = a00*b00 + a01*b10 + a02*b20 103 m.data[0][1] = a00*b01 + a01*b11 + a02*b21 104 m.data[0][2] = a00*b02 + a01*b12 + a02*b22 105 m.data[1][0] = a10*b00 + a11*b10 + a12*b20 106 m.data[1][1] = a10*b01 + a11*b11 + a12*b21 107 m.data[1][2] = a10*b02 + a11*b12 + a12*b22 108 m.data[2][0] = a20*b00 + a21*b10 + a22*b20 109 m.data[2][1] = a20*b01 + a21*b11 + a22*b21 110 m.data[2][2] = a20*b02 + a21*b12 + a22*b22 111 } 112 113 // RawMatrix returns the blas representation of the matrix with the backing 114 // data of this matrix. Changes to the returned matrix will be reflected in 115 // the receiver. 116 func (m *Mat) RawMatrix() blas64.General { 117 if m.data == nil { 118 m.data = new(array) 119 } 120 return blas64.General{Rows: 3, Cols: 3, Data: m.slice(), Stride: 3} 121 } 122 123 // Mat returns a 3×3 rotation matrix corresponding to the receiver. It 124 // may be used to perform rotations on a 3-vector or to apply the rotation 125 // to a 3×n matrix of column vectors. If the receiver is not a unit 126 // quaternion, the returned matrix will not be a pure rotation. 127 func (r Rotation) Mat() *Mat { 128 w, i, j, k := r.Real, r.Imag, r.Jmag, r.Kmag 129 ii := 2 * i * i 130 jj := 2 * j * j 131 kk := 2 * k * k 132 wi := 2 * w * i 133 wj := 2 * w * j 134 wk := 2 * w * k 135 ij := 2 * i * j 136 jk := 2 * j * k 137 ki := 2 * k * i 138 return &Mat{&array{ 139 {1 - (jj + kk), ij - wk, ki + wj}, 140 {ij + wk, 1 - (ii + kk), jk - wi}, 141 {ki - wj, jk + wi, 1 - (ii + jj)}, 142 }} 143 } 144 145 func arrayFrom(vals []float64) *array { 146 return (*array)(unsafe.Pointer(&vals[0])) 147 } 148 149 func (m *Mat) slice() []float64 { 150 return (*[9]float64)(unsafe.Pointer(m.data))[:] 151 }