func (array sparseCooF64Matrix) Shape() []int {
	return array.shape
}
A slice giving the size of all array dimensions
package matrix
import (
	"fmt"
)
type sparseCooF64Matrix struct {
	shape     []int
	values    []map[int]float64
	transpose bool
}
func (array sparseCooF64Matrix) Add(other ...NDArray) NDArray {
	return Add(&array, other...)
}
func (array sparseCooF64Matrix) All() bool {
	return All(&array)
}
func (array sparseCooF64Matrix) AllF(f func(v float64) bool) bool {
	return AllF(&array, f)
}
func (array sparseCooF64Matrix) AllF2(f func(v1, v2 float64) bool, other NDArray) bool {
	return AllF2(&array, f, other)
}
func (array sparseCooF64Matrix) Any() bool {
	return Any(&array)
}
func (array sparseCooF64Matrix) AnyF(f func(v float64) bool) bool {
	return AnyF(&array, f)
}
func (array sparseCooF64Matrix) AnyF2(f func(v1, v2 float64) bool, other NDArray) bool {
	return AnyF2(&array, f, other)
}
func (array sparseCooF64Matrix) Apply(f func(float64) float64) NDArray {
	return Apply(&array, f)
}
func (array sparseCooF64Matrix) Array() []float64 {
	return array.Dense().Array()
}
func (array *sparseCooF64Matrix) ColSet(col int, values []float64) {
	if col < 0 || col >= array.shape[1] {
		panic(fmt.Sprintf("ColSet can't set col %d of a %d-col array", col, array.shape[1]))
	} else if len(values) != array.shape[0] {
		panic(fmt.Sprintf("ColSet has %d rows but got %d values", array.shape[0], len(values)))
	}
	for row := 0; row < array.shape[0]; row++ {
		array.ItemSet(values[row], row, col)
	}
}
func (array sparseCooF64Matrix) Col(col int) []float64 {
	if col < 0 || col >= array.shape[1] {
		panic(fmt.Sprintf("Can't get column %d from a %dx%d array", col, array.shape[0], array.shape[1]))
	}
	result := make([]float64, array.shape[1])
	for row, val := range array.values {
		result[row] = val[col]
	}
	return result
}
func (array sparseCooF64Matrix) Cols() int {
	return array.shape[1]
}
func (array sparseCooF64Matrix) Concat(axis int, others ...NDArray) NDArray {
	return Concat(axis, &array, others...)
}
func (array sparseCooF64Matrix) Copy() NDArray {
	return array.copy()
}
func (array sparseCooF64Matrix) copy() *sparseCooF64Matrix {
	result := SparseCoo(array.shape[0], array.shape[1]).(*sparseCooF64Matrix)
	if array.transpose {
		for row, val := range array.values {
			for col, v := range val {
				result.values[col][row] = v
			}
		}
	} else {
		for row, val := range array.values {
			for col, v := range val {
				result.values[row][col] = v
			}
		}
	}
	return result
}
func (array sparseCooF64Matrix) CountNonzero() int {
	count := 0
	for _, val := range array.values {
		count += len(val)
	}
	return count
}
func (array sparseCooF64Matrix) Dense() NDArray {
	var result NDArray
	result = Dense(array.shape...)
	for row, val := range array.values {
		for col, v := range val {
			if array.transpose {
				result.ItemSet(v, col, row)
			} else {
				result.ItemSet(v, row, col)
			}
		}
	}
	return result
}
func (array sparseCooF64Matrix) Diag() Matrix {
	size := array.shape[0]
	if array.shape[1] < size {
		size = array.shape[1]
	}
	result := Dense(size, 1).M()
	for row, val := range array.values {
		result.ItemSet(val[row], row, 0)
	}
	return result
}
func (array sparseCooF64Matrix) Dist(t DistType) Matrix {
	return Dist(&array, t)
}
func (array sparseCooF64Matrix) Div(other ...NDArray) NDArray {
	return Div(&array, other...)
}
func (array sparseCooF64Matrix) Equal(other NDArray) bool {
	return Equal(&array, other)
}
func (array sparseCooF64Matrix) Fill(value float64) {
	panic("Can't Fill() a sparse coo matrix")
}
func (array sparseCooF64Matrix) FlatCoord(index int) []int {
	return flatToNd(array.shape, index)
}
func (array sparseCooF64Matrix) FlatItem(index int) float64 {
	nd := flatToNd(array.shape, index)
	return array.Item(nd[0], nd[1])
}
func (array *sparseCooF64Matrix) FlatItemSet(value float64, index int) {
	nd := flatToNd(array.shape, index)
	if array.transpose {
		array.ItemSet(value, nd[0], nd[1])
	}
	array.ItemSet(value, nd[0], nd[1])
}
func (array sparseCooF64Matrix) Inverse() (Matrix, error) {
	return Inverse(&array)
}
func (array sparseCooF64Matrix) Item(index ...int) float64 {
	if len(index) != 2 || index[0] >= array.shape[0] || index[1] >= array.shape[1] {
		panic(fmt.Sprintf("Item indices %v invalid for array shape %v", index, array.shape))
	}
	if array.transpose {
		index[0], index[1] = index[1], index[0]
	}
	return array.values[index[0]][index[1]]
}
func (array *sparseCooF64Matrix) ItemAdd(value float64) NDArray {
	result := WithValue(value, array.shape...)
	for row, val := range array.values {
		for col, v := range val {
			if array.transpose {
				result.ItemSet(v+value, col, row)
			} else {
				result.ItemSet(v+value, row, col)
			}
		}
	}
	return result
}
func (array *sparseCooF64Matrix) ItemDiv(value float64) NDArray {
	result := Dense(array.shape...)
	for row, val := range array.values {
		for col, v := range val {
			if array.transpose {
				result.ItemSet(v/value, col, row)
			} else {
				result.ItemSet(v/value, row, col)
			}
		}
	}
	return result
}
func (array *sparseCooF64Matrix) ItemProd(value float64) NDArray {
	result := Dense(array.shape...)
	for row, val := range array.values {
		for col, v := range val {
			if array.transpose {
				result.ItemSet(v*value, col, row)
			} else {
				result.ItemSet(v*value, row, col)
			}
		}
	}
	return result
}
func (array *sparseCooF64Matrix) ItemSub(value float64) NDArray {
	result := WithValue(-value, array.shape...)
	for row, val := range array.values {
		for col, v := range val {
			if array.transpose {
				result.ItemSet(v-value, col, row)
			} else {
				result.ItemSet(v-value, row, col)
			}
		}
	}
	return result
}
func (array *sparseCooF64Matrix) ItemSet(value float64, index ...int) {
	if len(index) != 2 || index[0] >= array.shape[0] || index[1] >= array.shape[1] {
		panic(fmt.Sprintf("Item indices %v invalid for array shape %v", index, array.shape))
	}
	if array.transpose {
		index[0], index[1] = index[1], index[0]
	}
	if value == 0 {
		delete(array.values[index[0]], index[1])
	} else {
		array.values[index[0]][index[1]] = value
	}
}
func (array sparseCooF64Matrix) LDivide(b Matrix) Matrix {
	return LDivide(&array, b)
}
func (array sparseCooF64Matrix) MProd(others ...Matrix) Matrix {
	return MProd(&array, others...)
}
func (array sparseCooF64Matrix) Max() float64 {
	return Max(&array)
}
func (array sparseCooF64Matrix) Min() float64 {
	return Min(&array)
}
func (array sparseCooF64Matrix) NDim() int {
	return len(array.shape)
}
func (array sparseCooF64Matrix) Norm(ord float64) float64 {
	return Norm(&array, ord)
}
func (array *sparseCooF64Matrix) Normalize() NDArray {
	return Normalize(array)
}
func (array sparseCooF64Matrix) Prod(other ...NDArray) NDArray {
	return Prod(&array, other...)
}
func (array sparseCooF64Matrix) Ravel() NDArray {
	return Ravel(&array)
}
func (array *sparseCooF64Matrix) RowSet(row int, values []float64) {
	if row < 0 || row >= array.shape[0] {
		panic(fmt.Sprintf("RowSet can't set row %d of a %d-row array", row, array.shape[0]))
	} else if len(values) != array.shape[1] {
		panic(fmt.Sprintf("RowSet has %d columns but got %d values", array.shape[1], len(values)))
	}
	for col := 0; col < array.shape[1]; col++ {
		array.ItemSet(values[col], row, col)
	}
}
func (array sparseCooF64Matrix) Row(row int) []float64 {
	if row < 0 || row >= array.shape[0] {
		panic(fmt.Sprintf("Can't get row %d from a %dx%d array", row, array.shape[0], array.shape[1]))
	}
	result := make([]float64, array.shape[0])
	for col, val := range array.values[row] {
		result[col] = val
	}
	return result
}
func (array sparseCooF64Matrix) Rows() int {
	return array.shape[0]
}