func AnyF2(array NDArray, f func(v1, v2 float64) bool, other NDArray) bool {
	sh1 := array.Shape()
	sh2 := other.Shape()
	if len(sh1) != len(sh2) {
		panic("AnyF2() requires two arrays of the same shape")
	}
	for i := 0; i < len(sh1); i++ {
		if sh1[i] != sh2[i] {
			panic("AnyF2() requires two arrays of the same shape")
		}
	}
	size := array.Size()
	for i := 0; i < size; i++ {
		if f(array.FlatItem(i), other.FlatItem(i)) {
			return true
		}
	}
	return false
}
Returns true if f is true for any pair of array elements in the same position
package matrix
import (
	"fmt"
	"math"
)
func ndToFlat(shape []int, index []int) int {
	if len(index) != len(shape) {
		panic(fmt.Sprintf("Indices %v invalid for array shape %v", index, shape))
	}
	flat := 0
	for i := range shape {
		if index[i] >= shape[i] || index[i] < -shape[i] {
			panic(fmt.Sprintf("Indices %v invalid for array shape %v", index, shape))
		} else if index[i] < 0 {
			flat += index[i] + shape[i]
		} else {
			flat += index[i]
		}
		if i < len(shape)-1 {
			flat *= shape[i+1]
		}
	}
	return flat
}
func flatToNd(shape []int, flat int) []int {
	size := 1
	for _, v := range shape {
		size *= v
	}
	if flat >= size || flat < -size {
		panic(fmt.Sprintf("Flat index %v invalid for array shape %v", flat, shape))
	}
	if flat < 0 {
		flat += size
	}
	index := make([]int, len(shape))
	for axis := 0; axis < len(index); axis++ {
		index[axis] = flat
		for a2 := axis + 1; a2 < len(index); a2++ {
			index[axis] /= shape[a2]
		}
		index[axis] %= shape[axis]
	}
	return index
}
func Add(array NDArray, others ...NDArray) NDArray {
	var result NDArray
	sp := array.Sparsity()
	sh := array.Shape()
	for _, o := range others {
		switch o.Sparsity() {
		case DenseArray:
			sp = DenseArray
		case SparseCooMatrix:
			if sp == SparseDiagMatrix {
				sp = SparseCooMatrix
			}
		}
		sh2 := o.Shape()
		if len(sh2) != len(sh) {
			panic(fmt.Sprintf("Can't add arrays with shapes %v and %v", sh, sh2))
		}
		for i := range sh {
			if sh[i] != sh2[i] {
				panic(fmt.Sprintf("Can't add arrays with shapes %v and %v", sh, sh2))
			}
		}
	}
	switch sp {
	case array.Sparsity():
		result = array.Copy()
	case DenseArray:
		result = array.Dense()
	case SparseCooMatrix:
		result = SparseCoo(sh[0], sh[1])
		array.VisitNonzero(func(pos []int, value float64) bool {
			result.ItemSet(value, pos...)
			return true
		})
	}
	for _, o := range others {
		o.VisitNonzero(func(pos []int, value float64) bool {
			result.ItemSet(result.Item(pos...)+value, pos...)
			return true
		})
	}
	return result
}
func All(array NDArray) bool {
	switch array.Sparsity() {
	case SparseDiagMatrix:
		return false
	default:
		return array.CountNonzero() == array.Size()
	}
}
func AllF(array NDArray, f func(v float64) bool) bool {
	counted := 0
	all := array.VisitNonzero(func(pos []int, value float64) bool {
		counted++
		if !f(value) {
			return false
		}
		return true
	})
	if !all || (counted < array.Size() && !f(0)) {
		return false
	}
	return true
}
func AllF2(array NDArray, f func(v1, v2 float64) bool, other NDArray) bool {
	sh1 := array.Shape()
	sh2 := other.Shape()
	if len(sh1) != len(sh2) {
		panic("AllF2() requires two arrays of the same shape")
	}
	for i := 0; i < len(sh1); i++ {
		if sh1[i] != sh2[i] {
			panic("AllF2() requires two arrays of the same shape")
		}
	}
	size := array.Size()
	for i := 0; i < size; i++ {
		if !f(array.FlatItem(i), other.FlatItem(i)) {
			return false
		}
	}
	return true
}
func Any(array NDArray) bool {
	return !array.VisitNonzero(func(pos []int, value float64) bool {
		return false
	})
}
func AnyF(array NDArray, f func(v float64) bool) bool {
	counted := 0
	allFalse := array.VisitNonzero(func(pos []int, value float64) bool {
		counted++
		if f(value) {
			return false
		}
		return true
	})
	if !allFalse || (counted < array.Size() && f(0)) {
		return true
	}
	return false
}