func (tsr *Bits) MetaData(key string) (string, bool) {
	if tsr.Meta == nil {
		return "", false
	}
	val, ok := tsr.Meta[key]
	return val, ok
}
MetaData retrieves value of given key, bool = false if not set
package etensor
import (
	"errors"
	"fmt"
	"log"
	"strings"
	"github.com/apache/arrow/go/arrow"
	"github.com/emer/etable/bitslice"
	"github.com/goki/ki/ints"
	"github.com/goki/ki/kit"
	"gonum.org/v1/gonum/mat"
)
type BoolType struct{}
func (t *BoolType) ID() arrow.Type { return arrow.BOOL }
func (t *BoolType) Name() string   { return "bool" }
func (t *BoolType) BitWidth() int  { return 1 }
type Bits struct {
	Shape
	Values bitslice.Slice
	Meta   map[string]string
}
func NewBits(shape, strides []int, names []string) *Bits {
	bt := &Bits{}
	bt.SetShape(shape, strides, names)
	ln := bt.Len()
	bt.Values = bitslice.Make(ln, 0)
	return bt
}
func NewBitsShape(shape *Shape) *Bits {
	bt := &Bits{}
	bt.CopyShape(shape)
	ln := bt.Len()
	bt.Values = bitslice.Make(ln, 0)
	return bt
}
func (tsr *Bits) ShapeObj() *Shape { return &tsr.Shape }
func (tsr *Bits) DataType() Type   { return BOOL }
func (tsr *Bits) Value(i []int) bool { j := int(tsr.Offset(i)); return tsr.Values.Index(j) }
func (tsr *Bits) Value1D(i int) bool { return tsr.Values.Index(i) }
func (tsr *Bits) Set(i []int, val bool) { j := int(tsr.Offset(i)); tsr.Values.Set(j, val) }
func (tsr *Bits) Set1D(i int, val bool) { tsr.Values.Set(i, val) }
func (tsr *Bits) IsNull(i []int) bool       { return false }
func (tsr *Bits) IsNull1D(i int) bool       { return false }
func (tsr *Bits) SetNull(i []int, nul bool) {}
func (tsr *Bits) SetNull1D(i int, nul bool) {}
func Float64ToBool(val float64) bool {
	bv := true
	if val == 0 {
		bv = false
	}
	return bv
}
func BoolToFloat64(bv bool) float64 {
	if bv {
		return 1
	} else {
		return 0
	}
}
func (tsr *Bits) FloatVal(i []int) float64 {
	j := tsr.Offset(i)
	return BoolToFloat64(tsr.Values.Index(j))
}
func (tsr *Bits) SetFloat(i []int, val float64) {
	j := tsr.Offset(i)
	tsr.Values.Set(j, Float64ToBool(val))
}
func (tsr *Bits) StringVal(i []int) string {
	j := tsr.Offset(i)
	return kit.ToString(tsr.Values.Index(j))
}
func (tsr *Bits) SetString(i []int, val string) {
	if bv, ok := kit.ToBool(val); ok {
		j := tsr.Offset(i)
		tsr.Values.Set(j, bv)
	}
}
func (tsr *Bits) FloatVal1D(off int) float64 {
	return BoolToFloat64(tsr.Values.Index(off))
}
func (tsr *Bits) SetFloat1D(off int, val float64) {
	tsr.Values.Set(off, Float64ToBool(val))
}
func (tsr *Bits) FloatValRowCell(row, cell int) float64 {
	_, sz := tsr.RowCellSize()
	return BoolToFloat64(tsr.Values.Index(row*sz + cell))
}
func (tsr *Bits) SetFloatRowCell(row, cell int, val float64) {
	_, sz := tsr.RowCellSize()
	tsr.Values.Set(row*sz+cell, Float64ToBool(val))
}
func (tsr *Bits) Floats(flt *[]float64) {
	sz := tsr.Len()
	SetFloat64SliceLen(flt, sz)
	for j := 0; j < sz; j++ {
		(*flt)[j] = BoolToFloat64(tsr.Values.Index(j))
	}
}
func (tsr *Bits) SetFloats(vals []float64) {
	sz := ints.MinInt(tsr.Len(), len(vals))
	for j := 0; j < sz; j++ {
		tsr.Values.Set(j, Float64ToBool(vals[j]))
	}
}
func (tsr *Bits) StringVal1D(off int) string {
	return kit.ToString(tsr.Values.Index(off))
}
func (tsr *Bits) SetString1D(off int, val string) {
	if bv, ok := kit.ToBool(val); ok {
		tsr.Values.Set(off, bv)
	}
}
func (tsr *Bits) StringValRowCell(row, cell int) string {
	_, sz := tsr.RowCellSize()
	return kit.ToString(tsr.Values.Index(row*sz + cell))
}
func (tsr *Bits) SetStringRowCell(row, cell int, val string) {
	if bv, ok := kit.ToBool(val); ok {
		_, sz := tsr.RowCellSize()
		tsr.Values.Set(row*sz+cell, bv)
	}
}
func (tsr *Bits) SubSpace(offs []int) Tensor {
	return nil
}
func (tsr *Bits) SubSpaceTry(offs []int) (Tensor, error) {
	return nil, errors.New("etensor.Bits does not support SubSpace")
}
func (tsr *Bits) Range() (min, max float64, minIdx, maxIdx int) {
	minIdx = -1
	maxIdx = -1
	return
}
func (tsr *Bits) Agg(ini float64, fun AggFunc) float64 {
	ln := tsr.Len()
	ag := ini
	for j := 0; j < ln; j++ {
		ag = fun(j, BoolToFloat64(tsr.Values.Index(j)), ag)
	}
	return ag
}
func (tsr *Bits) Eval(res *[]float64, fun EvalFunc) {
	ln := tsr.Len()
	if len(*res) != ln {
		*res = make([]float64, ln)
	}
	for j := 0; j < ln; j++ {
		(*res)[j] = fun(j, BoolToFloat64(tsr.Values.Index(j)))
	}
}
func (tsr *Bits) SetFunc(fun EvalFunc) {
	ln := tsr.Len()
	for j := 0; j < ln; j++ {
		tsr.Values.Set(j, Float64ToBool(fun(j, BoolToFloat64(tsr.Values.Index(j)))))
	}
}
func (tsr *Bits) SetZeros() {
	ln := tsr.Len()
	for j := 0; j < ln; j++ {
		tsr.Values.Set(j, false)
	}
}
func (tsr *Bits) Clone() Tensor {
	csr := NewBitsShape(&tsr.Shape)
	csr.Values = tsr.Values.Clone()
	return csr
}
func (tsr *Bits) CopyFrom(frm Tensor) {
	if fsm, ok := frm.(*Bits); ok {
		copy(tsr.Values, fsm.Values)
		return
	}
	sz := ints.MinInt(len(tsr.Values), frm.Len())
	for i := 0; i < sz; i++ {
		tsr.Values.Set(i, Float64ToBool(frm.FloatVal1D(i)))
	}
}
func (tsr *Bits) CopyShapeFrom(frm Tensor) {
	tsr.SetShape(frm.Shapes(), frm.Strides(), frm.DimNames())
}
func (tsr *Bits) CopyCellsFrom(frm Tensor, to, start, n int) {
	if fsm, ok := frm.(*Bits); ok {
		for i := 0; i < n; i++ {
			tsr.Values.Set(to+i, fsm.Values.Index(start+i))
		}
		return
	}
	for i := 0; i < n; i++ {
		tsr.Values.Set(to+i, Float64ToBool(frm.FloatVal1D(start+i)))
	}
}
func (tsr *Bits) SetShape(shape, strides []int, names []string) {
	tsr.Shape.SetShape(shape, strides, names)
	nln := tsr.Len()
	tsr.Values.SetLen(nln)
}
func (tsr *Bits) SetNumRows(rows int) {
	if !tsr.IsRowMajor() {
		return
	}
	rows = ints.MaxInt(1, rows)  
	cln := tsr.Len()
	crows := tsr.Dim(0)
	inln := cln / crows  
	nln := rows * inln
	tsr.Shape.Shp[0] = rows
	tsr.Values.SetLen(nln)
}
func (tsr *Bits) Dims() (r, c int) {
	log.Println("etensor Dims gonum Matrix call made on Bits Tensor -- not supported")
	return 0, 0
}
func (tsr *Bits) At(i, j int) float64 {
	log.Println("etensor At gonum Matrix call made on Bits Tensor -- not supported")
	return 0
}
func (tsr *Bits) T() mat.Matrix {
	log.Println("etensor T gonum Matrix call made on Bits Tensor -- not supported")
	return mat.Transpose{tsr}
}
func (tsr *Bits) Label() string {
	return fmt.Sprintf("Bits: %s", tsr.Shape.String())
}
func (tsr *Bits) String() string {
	str := tsr.Label()
	sz := tsr.Len()
	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("%g ", vl))
		}
		b.WriteString("\n")
	}
	return b.String()
}
func (tsr *Bits) SetMetaData(key, val string) {
	if tsr.Meta == nil {
		tsr.Meta = make(map[string]string)
	}
	tsr.Meta[key] = val
}