Tensor computes a similarity / distance matrix on tensor using given metric function. Outer-most dimension ("rows") is used as "indexical" dimension and all other dimensions within that are compared. Results go in smat which is ensured to have proper square 2D shape (rows * rows).
(smat tensor.Tensor, a tensor.Tensor, mfun metric.Func64)
| 18 | // Results go in smat which is ensured to have proper square 2D shape |
| 19 | // (rows * rows). |
| 20 | func Tensor(smat tensor.Tensor, a tensor.Tensor, mfun metric.Func64) error { |
| 21 | rows := a.DimSize(0) |
| 22 | nd := a.NumDims() |
| 23 | if nd < 2 || rows == 0 { |
| 24 | return fmt.Errorf("simat.Tensor: must have 2 or more dims and rows != 0") |
| 25 | } |
| 26 | ln := a.Len() |
| 27 | sz := ln / rows |
| 28 | |
| 29 | sshp := []int{rows, rows} |
| 30 | smat.SetShape(sshp) |
| 31 | |
| 32 | av := make([]float64, sz) |
| 33 | bv := make([]float64, sz) |
| 34 | ardim := []int{0} |
| 35 | brdim := []int{0} |
| 36 | sdim := []int{0, 0} |
| 37 | for ai := 0; ai < rows; ai++ { |
| 38 | ardim[0] = ai |
| 39 | sdim[0] = ai |
| 40 | ar := a.SubSpace(ardim) |
| 41 | ar.Floats(&av) |
| 42 | for bi := 0; bi <= ai; bi++ { // lower diag |
| 43 | brdim[0] = bi |
| 44 | sdim[1] = bi |
| 45 | br := a.SubSpace(brdim) |
| 46 | br.Floats(&bv) |
| 47 | sv := mfun(av, bv) |
| 48 | smat.SetFloat(sdim, sv) |
| 49 | } |
| 50 | } |
| 51 | // now fill in upper diagonal with values from lower diagonal |
| 52 | // note: assumes symmetric distance function |
| 53 | fdim := []int{0, 0} |
| 54 | for ai := 0; ai < rows; ai++ { |
| 55 | sdim[0] = ai |
| 56 | fdim[1] = ai |
| 57 | for bi := ai + 1; bi < rows; bi++ { // upper diag |
| 58 | fdim[0] = bi |
| 59 | sdim[1] = bi |
| 60 | sv := smat.Float(fdim) |
| 61 | smat.SetFloat(sdim, sv) |
| 62 | } |
| 63 | } |
| 64 | return nil |
| 65 | } |
| 66 | |
| 67 | // Tensors computes a similarity / distance matrix on two tensors |
| 68 | // using given metric function. Outer-most dimension ("rows") is |