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")
}
SubSpaceTry returns a new tensor with innermost subspace at given
offset(s) in outermost dimension(s) (len(offs) < NumDims).
Try version returns an error message if the offs do not fit in tensor Shape.
Only valid for row or column major layouts.
The new tensor points to the values of the this tensor (i.e., modifications
will affect both), as its Values slice is a view onto the original (which
is why only inner-most contiguous supsaces are supported).
Use Clone() method to separate the two.
Null value bits are NOT shared but are copied if present.
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
}