func (tsr *Uint64) SetZeros() {
	for j := range tsr.Values {
		tsr.Values[j] = 0
	}
}
SetZeros is simple convenience function initialize all values to 0
package etensor
import (
	"errors"
	"fmt"
	"log"
	"math"
	"strconv"
	"strings"
	"github.com/apache/arrow/go/arrow"
	"github.com/apache/arrow/go/arrow/array"
	"github.com/apache/arrow/go/arrow/memory"
	"github.com/apache/arrow/go/arrow/tensor"
	"github.com/emer/etable/bitslice"
	"github.com/goki/ki/ints"
	"github.com/goki/ki/kit"
	"gonum.org/v1/gonum/mat"
)
type Int64 struct {
	Shape
	Values []int64
	Nulls  bitslice.Slice
	Meta   map[string]string
}
func NewInt64(shape, strides []int, names []string) *Int64 {
	tsr := &Int64{}
	tsr.SetShape(shape, strides, names)
	tsr.Values = make([]int64, tsr.Len())
	return tsr
}
func NewInt64Shape(shape *Shape, vals []int64) *Int64 {
	tsr := &Int64{}
	tsr.CopyShape(shape)
	if vals != nil {
		if len(vals) != tsr.Len() {
			log.Printf("etensor.New*Shape: length of provided vals: %d not proper length: %d", len(vals), tsr.Len())
			tsr.Values = make([]int64, tsr.Len())
		} else {
			tsr.Values = vals
		}
	} else {
		tsr.Values = make([]int64, tsr.Len())
	}
	return tsr
}
func (tsr *Int64) ShapeObj() *Shape       { return &tsr.Shape }
func (tsr *Int64) DataType() Type         { return INT64 }
func (tsr *Int64) Value(i []int) int64    { j := tsr.Offset(i); return tsr.Values[j] }
func (tsr *Int64) Value1D(i int) int64    { return tsr.Values[i] }
func (tsr *Int64) Set(i []int, val int64) { j := tsr.Offset(i); tsr.Values[j] = val }
func (tsr *Int64) Set1D(i int, val int64) { tsr.Values[i] = val }
func (tsr *Int64) IsNull(i []int) bool {
	if tsr.Nulls == nil {
		return false
	}
	j := tsr.Offset(i)
	return tsr.Nulls.Index(j)
}
func (tsr *Int64) IsNull1D(i int) bool {
	if tsr.Nulls == nil {
		return false
	}
	return tsr.Nulls.Index(i)
}
func (tsr *Int64) SetNull(i []int, nul bool) {
	if tsr.Nulls == nil {
		tsr.Nulls = bitslice.Make(tsr.Len(), 0)
	}
	j := tsr.Offset(i)
	tsr.Nulls.Set(j, nul)
}
func (tsr *Int64) SetNull1D(i int, nul bool) {
	if tsr.Nulls == nil {
		tsr.Nulls = bitslice.Make(tsr.Len(), 0)
	}
	tsr.Nulls.Set(i, nul)
}
func (tsr *Int64) FloatVal(i []int) float64      { j := tsr.Offset(i); return float64(tsr.Values[j]) }
func (tsr *Int64) SetFloat(i []int, val float64) { j := tsr.Offset(i); tsr.Values[j] = int64(val) }
func (tsr *Int64) StringVal(i []int) string { j := tsr.Offset(i); return kit.ToString(tsr.Values[j]) }
func (tsr *Int64) SetString(i []int, val string) {
	if fv, err := strconv.ParseFloat(val, 64); err == nil {
		j := tsr.Offset(i)
		tsr.Values[j] = int64(fv)
	}
}
func (tsr *Int64) FloatVal1D(off int) float64      { return float64(tsr.Values[off]) }
func (tsr *Int64) SetFloat1D(off int, val float64) { tsr.Values[off] = int64(val) }
func (tsr *Int64) FloatValRowCell(row, cell int) float64 {
	_, sz := tsr.RowCellSize()
	return float64(tsr.Values[row*sz+cell])
}
func (tsr *Int64) SetFloatRowCell(row, cell int, val float64) {
	_, sz := tsr.RowCellSize()
	tsr.Values[row*sz+cell] = int64(val)
}
func (tsr *Int64) Floats(flt *[]float64) {
	SetFloat64SliceLen(flt, len(tsr.Values))
	for j, vl := range tsr.Values {
		(*flt)[j] = float64(vl)
	}
}
func (tsr *Int64) SetFloats(vals []float64) {
	sz := ints.MinInt(len(tsr.Values), len(vals))
	for j := 0; j < sz; j++ {
		tsr.Values[j] = int64(vals[j])
	}
}
func (tsr *Int64) StringVal1D(off int) string { return kit.ToString(tsr.Values[off]) }
func (tsr *Int64) SetString1D(off int, val string) {
	if fv, err := strconv.ParseFloat(val, 64); err == nil {
		tsr.Values[off] = int64(fv)
	}
}
func (tsr *Int64) StringValRowCell(row, cell int) string {
	_, sz := tsr.RowCellSize()
	return kit.ToString(tsr.Values[row*sz+cell])
}
func (tsr *Int64) SetStringRowCell(row, cell int, val string) {
	if fv, err := strconv.ParseFloat(val, 64); err == nil {
		_, sz := tsr.RowCellSize()
		tsr.Values[row*sz+cell] = int64(fv)
	}
}
func (tsr *Int64) Range() (min, max float64, minIdx, maxIdx int) {
	minIdx = -1
	maxIdx = -1
	for j, vl := range tsr.Values {
		fv := float64(vl)
		if math.IsNaN(fv) {
			continue
		}
		if fv < min || minIdx < 0 {
			min = fv
			minIdx = j
		}
		if fv > max || maxIdx < 0 {
			max = fv
			maxIdx = j
		}
	}
	return
}
func (tsr *Int64) Agg(ini float64, fun AggFunc) float64 {
	ag := ini
	for j, vl := range tsr.Values {
		val := float64(vl)
		if !tsr.IsNull1D(j) && !math.IsNaN(val) {
			ag = fun(j, val, ag)
		}
	}
	return ag
}
func (tsr *Int64) Eval(res *[]float64, fun EvalFunc) {
	ln := tsr.Len()
	if len(*res) != ln {
		*res = make([]float64, ln)
	}
	for j, vl := range tsr.Values {
		val := float64(vl)
		if !tsr.IsNull1D(j) && !math.IsNaN(val) {
			(*res)[j] = fun(j, val)
		}
	}
}
func (tsr *Int64) SetFunc(fun EvalFunc) {
	for j, vl := range tsr.Values {
		val := float64(vl)
		if !tsr.IsNull1D(j) && !math.IsNaN(val) {
			tsr.Values[j] = int64(fun(j, val))
		}
	}
}
func (tsr *Int64) SetZeros() {
	for j := range tsr.Values {
		tsr.Values[j] = 0
	}
}
func (tsr *Int64) Clone() Tensor {
	csr := NewInt64Shape(&tsr.Shape, nil)
	copy(csr.Values, tsr.Values)
	if tsr.Nulls != nil {
		csr.Nulls = tsr.Nulls.Clone()
	}
	return csr
}
func (tsr *Int64) CopyFrom(frm Tensor) {
	if fsm, ok := frm.(*Int64); ok {
		copy(tsr.Values, fsm.Values)
		if fsm.Nulls != nil {
			if tsr.Nulls == nil {
				tsr.Nulls = bitslice.Make(tsr.Len(), 0)
			}
			copy(tsr.Nulls, fsm.Nulls)
		}
		return
	}
	sz := ints.MinInt(len(tsr.Values), frm.Len())
	for i := 0; i < sz; i++ {
		tsr.Values[i] = int64(frm.FloatVal1D(i))
		if frm.IsNull1D(i) {
			tsr.SetNull1D(i, true)
		}
	}
}
func (tsr *Int64) CopyShapeFrom(frm Tensor) {
	tsr.SetShape(frm.Shapes(), frm.Strides(), frm.DimNames())
}
func (tsr *Int64) CopyCellsFrom(frm Tensor, to, start, n int) {
	if fsm, ok := frm.(*Int64); ok {
		for i := 0; i < n; i++ {
			tsr.Values[to+i] = fsm.Values[start+i]
			if fsm.IsNull1D(start + i) {
				tsr.SetNull1D(to+i, true)
			}
		}
		return
	}
	for i := 0; i < n; i++ {
		tsr.Values[to+i] = int64(frm.FloatVal1D(start + i))
		if frm.IsNull1D(start + i) {
			tsr.SetNull1D(to+i, true)
		}
	}
}
func (tsr *Int64) SetShape(shape, strides []int, names []string) {
	tsr.Shape.SetShape(shape, strides, names)
	nln := tsr.Len()
	if cap(tsr.Values) >= nln {
		tsr.Values = tsr.Values[0:nln]
	} else {
		nv := make([]int64, nln)
		copy(nv, tsr.Values)
		tsr.Values = nv
	}
	if tsr.Nulls != nil {
		tsr.Nulls.SetLen(nln)
	}
}
func (tsr *Int64) SetNumRows(rows int) {
	if !tsr.IsRowMajor() {
		return
	}
	rows = ints.MaxInt(1, rows)  
	_, cells := tsr.RowCellSize()
	nln := rows * cells
	tsr.Shape.Shp[0] = rows
	if cap(tsr.Values) >= nln {
		tsr.Values = tsr.Values[0:nln]
	} else {
		nv := make([]int64, nln)
		copy(nv, tsr.Values)
		tsr.Values = nv
	}
	if tsr.Nulls != nil {
		tsr.Nulls.SetLen(nln)
	}
}
func (tsr *Int64) SubSpace(offs []int) Tensor {
	ss, _ := tsr.SubSpaceTry(offs)
	return ss
}
func (tsr *Int64) SubSpaceTry(offs []int) (Tensor, error) {
	nd := tsr.NumDims()
	od := len(offs)
	if od >= nd {
		return nil, errors.New("SubSpace len(offsets) for outer dimensions was >= NumDims -- must be less")
	}
	id := nd - od
	if tsr.IsRowMajor() {
		stsr := &Int64{}
		stsr.SetShape(tsr.Shp[od:], nil, tsr.Nms[od:])  
		sti := make([]int, nd)
		copy(sti, offs)
		stoff := tsr.Offset(sti)
		sln := stsr.Len()
		stsr.Values = tsr.Values[stoff : stoff+sln]
		if tsr.Nulls != nil {
			stsr.Nulls = tsr.Nulls.SubSlice(stoff, stoff+sln)
		}
		return stsr, nil
	} else if tsr.IsColMajor() {
		stsr := &Int64{}
		stsr.SetShape(tsr.Shp[:id], nil, tsr.Nms[:id])
		stsr.Strd = ColMajorStrides(stsr.Shp)
		sti := make([]int, nd)
		for i := id; i < nd; i++ {
			sti[i] = offs[i-id]
		}
		stoff := tsr.Offset(sti)
		sln := stsr.Len()
		stsr.Values = tsr.Values[stoff : stoff+sln]
		if tsr.Nulls != nil {
			stsr.Nulls = tsr.Nulls.SubSlice(stoff, stoff+sln)
		}
		return stsr, nil
	}
	return nil, errors.New("SubSpace only valid for RowMajor or ColMajor tensors")
}
func (tsr *Int64) Label() string {
	return fmt.Sprintf("Int64: %s", tsr.Shape.String())
}
func (tsr *Int64) String() string {
	str := tsr.Label()
	sz := len(tsr.Values)
	if sz > 1000 {
		return str
	}
	var b strings.Builder
	b.WriteString(str)
	b.WriteString("\n")
	oddRow := true
	rows, cols, _, _ := Prjn2DShape(&tsr.Shape, oddRow)
	for r := 0; r < rows; r++ {
		rc, _ := Prjn2DCoords(&tsr.Shape, oddRow, r, 0)
		b.WriteString(fmt.Sprintf("%v: ", rc))
		for c := 0; c < cols; c++ {
			vl := Prjn2DVal(tsr, oddRow, r, c)
			b.WriteString(fmt.Sprintf("%7g ", vl))
		}
		b.WriteString("\n")
	}
	return b.String()
}
func (tsr *Int64) ToArrow() *tensor.Int64 {
	bld := array.NewInt64Builder(memory.DefaultAllocator)
	if tsr.Nulls != nil {
		bld.AppendValues(tsr.Values, tsr.Nulls.ToBools())
	} else {
		bld.AppendValues(tsr.Values, nil)
	}
	vec := bld.NewInt64Array()
	return tensor.NewInt64(vec.Data(), tsr.Shape64(), tsr.Strides64(), tsr.DimNames())
}
func (tsr *Int64) FromArrow(arw *tensor.Int64, cpy bool) {
	nms := make([]string, arw.NumDims())  
	for i := range nms {
		nms[i] = arw.DimName(i)
	}
	tsr.SetShape64(arw.Shape(), arw.Strides(), nms)
	if cpy {
		vls := arw.Int64Values()
		tsr.Values = make([]int64, tsr.Len())
		copy(tsr.Values, vls)
	} else {
		tsr.Values = arw.Int64Values()
	}
}
func (tsr *Int64) Dims() (r, c int) {
	nd := tsr.NumDims()
	if nd < 2 {
		log.Println("etensor Dims gonum Matrix call made on Tensor with dims < 2")
		return 0, 0
	}
	return tsr.Dim(nd - 2), tsr.Dim(nd - 1)
}
func (tsr *Int64) At(i, j int) float64 {
	nd := tsr.NumDims()
	if nd < 2 {
		log.Println("etensor Dims gonum Matrix call made on Tensor with dims < 2")
		return 0
	} else if nd == 2 {
		return tsr.FloatVal([]int{i, j})
	} else {
		ix := make([]int, nd)
		ix[nd-2] = i
		ix[nd-1] = j
		return tsr.FloatVal(ix)
	}
}
func (tsr *Int64) T() mat.Matrix {
	return mat.Transpose{tsr}
}
func (tsr *Int64) Symmetric() (r int) {
	nd := tsr.NumDims()
	if nd < 2 {
		log.Println("etensor Symmetric gonum Matrix call made on Tensor with dims < 2")
		return 0
	}
	if tsr.Dim(nd-2) != tsr.Dim(nd-1) {
		log.Println("etensor Symmatrics gonum Matrix call made on Tensor that is not symmetric")
		return 0
	}
	return tsr.Dim(nd - 1)
}
func (tsr *Int64) SetMetaData(key, val string) {
	if tsr.Meta == nil {
		tsr.Meta = make(map[string]string)
	}
	tsr.Meta[key] = val
}
func (tsr *Int64) MetaData(key string) (string, bool) {
	if tsr.Meta == nil {
		return "", false
	}
	val, ok := tsr.Meta[key]
	return val, ok
}
func (tsr *Int64) MetaDataMap() map[string]string {
	return tsr.Meta
}
func (tsr *Int64) CopyMetaData(frm Tensor) {
	fmap := frm.MetaDataMap()
	if len(fmap) == 0 {
		return
	}
	if tsr.Meta == nil {
		tsr.Meta = make(map[string]string)
	}
	for k, v := range fmap {
		tsr.Meta[k] = v
	}
}
type Uint64 struct {
	Shape
	Values []uint64
	Nulls  bitslice.Slice
	Meta   map[string]string
}
func NewUint64(shape, strides []int, names []string) *Uint64 {
	tsr := &Uint64{}
	tsr.SetShape(shape, strides, names)
	tsr.Values = make([]uint64, tsr.Len())
	return tsr
}
func NewUint64Shape(shape *Shape, vals []uint64) *Uint64 {
	tsr := &Uint64{}
	tsr.CopyShape(shape)
	if vals != nil {
		if len(vals) != tsr.Len() {
			log.Printf("etensor.New*Shape: length of provided vals: %d not proper length: %d", len(vals), tsr.Len())
			tsr.Values = make([]uint64, tsr.Len())
		} else {
			tsr.Values = vals
		}
	} else {
		tsr.Values = make([]uint64, tsr.Len())
	}
	return tsr
}
func (tsr *Uint64) ShapeObj() *Shape        { return &tsr.Shape }
func (tsr *Uint64) DataType() Type          { return UINT64 }
func (tsr *Uint64) Value(i []int) uint64    { j := tsr.Offset(i); return tsr.Values[j] }
func (tsr *Uint64) Value1D(i int) uint64    { return tsr.Values[i] }
func (tsr *Uint64) Set(i []int, val uint64) { j := tsr.Offset(i); tsr.Values[j] = val }
func (tsr *Uint64) Set1D(i int, val uint64) { tsr.Values[i] = val }
func (tsr *Uint64) IsNull(i []int) bool {
	if tsr.Nulls == nil {
		return false
	}
	j := tsr.Offset(i)
	return tsr.Nulls.Index(j)
}
func (tsr *Uint64) IsNull1D(i int) bool {
	if tsr.Nulls == nil {
		return false
	}
	return tsr.Nulls.Index(i)
}
func (tsr *Uint64) SetNull(i []int, nul bool) {
	if tsr.Nulls == nil {
		tsr.Nulls = bitslice.Make(tsr.Len(), 0)
	}
	j := tsr.Offset(i)
	tsr.Nulls.Set(j, nul)
}
func (tsr *Uint64) SetNull1D(i int, nul bool) {
	if tsr.Nulls == nil {
		tsr.Nulls = bitslice.Make(tsr.Len(), 0)
	}
	tsr.Nulls.Set(i, nul)
}
func (tsr *Uint64) FloatVal(i []int) float64      { j := tsr.Offset(i); return float64(tsr.Values[j]) }
func (tsr *Uint64) SetFloat(i []int, val float64) { j := tsr.Offset(i); tsr.Values[j] = uint64(val) }
func (tsr *Uint64) StringVal(i []int) string { j := tsr.Offset(i); return kit.ToString(tsr.Values[j]) }
func (tsr *Uint64) SetString(i []int, val string) {
	if fv, err := strconv.ParseFloat(val, 64); err == nil {
		j := tsr.Offset(i)
		tsr.Values[j] = uint64(fv)
	}
}
func (tsr *Uint64) FloatVal1D(off int) float64      { return float64(tsr.Values[off]) }
func (tsr *Uint64) SetFloat1D(off int, val float64) { tsr.Values[off] = uint64(val) }
func (tsr *Uint64) FloatValRowCell(row, cell int) float64 {
	_, sz := tsr.RowCellSize()
	return float64(tsr.Values[row*sz+cell])
}
func (tsr *Uint64) SetFloatRowCell(row, cell int, val float64) {
	_, sz := tsr.RowCellSize()
	tsr.Values[row*sz+cell] = uint64(val)
}
func (tsr *Uint64) Floats(flt *[]float64) {
	SetFloat64SliceLen(flt, len(tsr.Values))
	for j, vl := range tsr.Values {
		(*flt)[j] = float64(vl)
	}
}
func (tsr *Uint64) SetFloats(vals []float64) {
	sz := ints.MinInt(len(tsr.Values), len(vals))
	for j := 0; j < sz; j++ {
		tsr.Values[j] = uint64(vals[j])
	}
}
func (tsr *Uint64) StringVal1D(off int) string { return kit.ToString(tsr.Values[off]) }
func (tsr *Uint64) SetString1D(off int, val string) {
	if fv, err := strconv.ParseFloat(val, 64); err == nil {
		tsr.Values[off] = uint64(fv)
	}
}
func (tsr *Uint64) StringValRowCell(row, cell int) string {
	_, sz := tsr.RowCellSize()
	return kit.ToString(tsr.Values[row*sz+cell])
}
func (tsr *Uint64) SetStringRowCell(row, cell int, val string) {
	if fv, err := strconv.ParseFloat(val, 64); err == nil {
		_, sz := tsr.RowCellSize()
		tsr.Values[row*sz+cell] = uint64(fv)
	}
}
func (tsr *Uint64) Range() (min, max float64, minIdx, maxIdx int) {
	minIdx = -1
	maxIdx = -1
	for j, vl := range tsr.Values {
		fv := float64(vl)
		if math.IsNaN(fv) {
			continue
		}
		if fv < min || minIdx < 0 {
			min = fv
			minIdx = j
		}
		if fv > max || maxIdx < 0 {
			max = fv
			maxIdx = j
		}
	}
	return
}
func (tsr *Uint64) Agg(ini float64, fun AggFunc) float64 {
	ag := ini
	for j, vl := range tsr.Values {
		val := float64(vl)
		if !tsr.IsNull1D(j) && !math.IsNaN(val) {
			ag = fun(j, val, ag)
		}
	}
	return ag
}
func (tsr *Uint64) Eval(res *[]float64, fun EvalFunc) {
	ln := tsr.Len()
	if len(*res) != ln {
		*res = make([]float64, ln)
	}
	for j, vl := range tsr.Values {
		val := float64(vl)
		if !tsr.IsNull1D(j) && !math.IsNaN(val) {
			(*res)[j] = fun(j, val)
		}
	}
}
func (tsr *Uint64) SetFunc(fun EvalFunc) {
	for j, vl := range tsr.Values {
		val := float64(vl)
		if !tsr.IsNull1D(j) && !math.IsNaN(val) {
			tsr.Values[j] = uint64(fun(j, val))
		}
	}
}