tensor/print: added padding and precision

This commit is contained in:
sugarme 2020-11-09 17:16:34 +11:00
parent 5997cc1a2c
commit c1bbee4880
4 changed files with 148 additions and 25 deletions

View File

@ -49,29 +49,41 @@ import (
func basicOps() { func basicOps() {
// Initiate a tensor xs := ts.MustRand([]int64{3, 5, 6}, gotch.Float, gotch.CPU)
tensor := ts.MustArange1(ts.FloatScalar(0), ts.FloatScalar(12), gotch.Float, gotch.CPU).MustView([]int64{3, 4}, true) fmt.Printf("%8.3f\n", xs)
fmt.Printf("%i", xs)
tensor.Print() // output
// 0 1 2 3 /*
// 4 5 6 7 (1,.,.) =
// 8 9 10 11 0.391 0.055 0.638 0.514 0.757 0.446
// [ CPUFloatType{3,4} ] 0.817 0.075 0.437 0.452 0.077 0.492
0.504 0.945 0.863 0.243 0.254 0.640
0.850 0.132 0.763 0.572 0.216 0.116
0.410 0.660 0.156 0.336 0.885 0.391
fmt.Printf("tensor values: %v\n", tensor.Float64Values()) (2,.,.) =
//tensor values: [0 1 2 3 4 5 6 7 8 9 10 11] 0.952 0.731 0.380 0.390 0.374 0.001
0.455 0.142 0.088 0.039 0.862 0.939
0.621 0.198 0.728 0.914 0.168 0.057
0.655 0.231 0.680 0.069 0.803 0.243
0.853 0.729 0.983 0.534 0.749 0.624
fmt.Printf("tensor dtype: %v\n", tensor.DType()) (3,.,.) =
//tensor dtype: float32 0.734 0.447 0.914 0.956 0.269 0.000
0.427 0.034 0.477 0.535 0.440 0.972
0.407 0.945 0.099 0.184 0.778 0.058
0.482 0.996 0.085 0.605 0.282 0.671
0.887 0.029 0.005 0.216 0.354 0.262
fmt.Printf("tensor shape: %v\n", tensor.MustSize())
//tensor shape: [3 4]
fmt.Printf("tensor element number: %v\n", tensor.Numel())
//tensor element number: 12
// Delete a tensor (NOTE. tensor is created in C memory and will need to free up manually.) TENSOR INFO:
tensor.MustDrop() Shape: [3 5 6]
DType: float32
Device: {CPU 1}
Defined: true
*/
// Basic tensor operations // Basic tensor operations
ts1 := ts.MustArange(ts.IntScalar(6), gotch.Int64, gotch.CPU).MustView([]int64{2, 3}, true) ts1 := ts.MustArange(ts.IntScalar(6), gotch.Int64, gotch.CPU).MustView([]int64{2, 3}, true)

View File

@ -8,17 +8,18 @@ import (
) )
func main() { func main() {
intTensor() // intTensor()
floatTensor() floatTensor()
} }
func intTensor() { func intTensor() {
xs := ts.MustArange(ts.IntScalar(7*3*4*5*6), gotch.Int64, gotch.CPU).MustView([]int64{7, 3, 4, 5, 6}, true) xs := ts.MustArange(ts.IntScalar(7*3*4*5*6), gotch.Int64, gotch.CPU).MustView([]int64{7, 3, 4, 5, 6}, true)
fmt.Printf("%0.4d\n", xs) fmt.Printf("%4d\n", xs)
} }
func floatTensor() { func floatTensor() {
// xs := ts.MustRand([]int64{7, 3, 4, 5, 6}, gotch.Double, gotch.CPU) // xs := ts.MustRand([]int64{7, 3, 4, 5, 6}, gotch.Double, gotch.CPU)
xs := ts.MustRand([]int64{3, 5, 6}, gotch.Float, gotch.CPU) xs := ts.MustRand([]int64{3, 5, 6}, gotch.Float, gotch.CPU)
fmt.Printf("%.3f\n", xs) fmt.Printf("%8.3f\n", xs)
fmt.Printf("%i", xs)
} }

View File

@ -0,0 +1,71 @@
package tensor_test
import (
"fmt"
"github.com/sugarme/gotch"
ts "github.com/sugarme/gotch/tensor"
)
func ExampleTensor_MustArange1() {
tensor := ts.MustArange1(ts.FloatScalar(0), ts.FloatScalar(12), gotch.Int64, gotch.CPU).MustView([]int64{3, 4}, true)
fmt.Printf("%v", tensor)
// output
// 0 1 2 3
// 4 5 6 7
// 8 9 10 11
}
func ExampleTensor_Matmul() {
// Basic tensor operations
ts1 := ts.MustArange(ts.IntScalar(6), gotch.Int64, gotch.CPU).MustView([]int64{2, 3}, true)
defer ts1.MustDrop()
ts2 := ts.MustOnes([]int64{3, 4}, gotch.Int64, gotch.CPU)
defer ts2.MustDrop()
mul := ts1.MustMatmul(ts2, false)
defer mul.MustDrop()
fmt.Println("ts1: ")
ts1.Print()
fmt.Println("ts2: ")
ts2.Print()
fmt.Println("mul tensor (ts1 x ts2): ")
mul.Print()
//ts1:
// 0 1 2
// 3 4 5
//[ CPULongType{2,3} ]
//ts2:
// 1 1 1 1
// 1 1 1 1
// 1 1 1 1
//[ CPULongType{3,4} ]
//mul tensor (ts1 x ts2):
// 3 3 3 3
// 12 12 12 12
//[ CPULongType{2,4} ]
}
func ExampleTensor_Add1_() {
// In-place operation
ts3 := ts.MustOnes([]int64{2, 3}, gotch.Float, gotch.CPU)
fmt.Println("Before:")
ts3.Print()
ts3.MustAdd1_(ts.FloatScalar(2.0))
fmt.Printf("After (ts3 + 2.0): \n")
ts3.Print()
ts3.MustDrop()
//Before:
// 1 1 1
// 1 1 1
//[ CPUFloatType{2,3} ]
//After (ts3 + 2.0):
// 3 3 3
// 3 3 3
//[ CPUFloatType{2,3} ]
}

View File

@ -152,10 +152,12 @@ func (ts *Tensor) Format(s fmt.State, c rune) {
return return
} }
f := newFmtState(s, c, shape)
data := ts.ValueGo() data := ts.ValueGo()
f := newFmtState(s, c, shape)
f.setWidth(data)
f.makePad()
// 0d (scalar) // 0d (scalar)
if len(shape) == 0 { if len(shape) == 0 {
fmt.Printf("%v", data) fmt.Printf("%v", data)
@ -188,15 +190,23 @@ func (ts *Tensor) Format(s fmt.State, c rune) {
// fmtState is a struct that implements fmt.State interface // fmtState is a struct that implements fmt.State interface
type fmtState struct { type fmtState struct {
fmt.State fmt.State
c rune c rune // format verb
pad []byte // padding
w int // width
p int // precision
shape []int64 shape []int64
buf *bytes.Buffer buf *bytes.Buffer
} }
func newFmtState(s fmt.State, c rune, shape []int64) *fmtState { func newFmtState(s fmt.State, c rune, shape []int64) *fmtState {
w, _ := s.Width()
p, _ := s.Precision()
return &fmtState{ return &fmtState{
State: s, State: s,
c: c, c: c,
w: w,
p: p,
shape: shape, shape: shape,
buf: bytes.NewBuffer(make([]byte, 0)), buf: bytes.NewBuffer(make([]byte, 0)),
} }
@ -270,9 +280,10 @@ func (f *fmtState) writeSlice(data interface{}) {
el := reflect.ValueOf(data).Index(i).Interface() el := reflect.ValueOf(data).Index(i).Interface()
// TODO: more format options here // TODO: more format options here
fmt.Fprintf(f.buf, format, el) w, _ := fmt.Fprintf(f.buf, format, el)
f.Write(f.buf.Bytes()) f.Write(f.buf.Bytes())
f.Write([]byte(" ")) f.Write(f.pad[:f.w-w]) // prepad
f.Write(f.pad[:2]) // pad
f.buf.Reset() f.buf.Reset()
} }
@ -297,6 +308,27 @@ func (f *fmtState) cleanFmt() string {
return buf.String() return buf.String()
} }
func (f *fmtState) makePad() {
f.pad = make([]byte, maxInt(f.w, 4))
for i := range f.pad {
f.pad[i] = ' '
}
}
// setWidth determines maximal width from input data and set to `w` field
func (f *fmtState) setWidth(data interface{}) {
format := f.cleanFmt()
f.w = 0
for i := 0; i < reflect.ValueOf(data).Len(); i++ {
el := reflect.ValueOf(data).Index(i).Interface()
w, _ := fmt.Fprintf(f.buf, format, el)
if w > f.w {
f.w = w
}
f.buf.Reset()
}
}
func shapeToSize(shape []int64) int { func shapeToSize(shape []int64) int {
n := 1 n := 1
for _, v := range shape { for _, v := range shape {
@ -307,3 +339,10 @@ func shapeToSize(shape []int64) int {
} }
return n return n
} }
func maxInt(a, b int) int {
if a >= b {
return a
}
return b
}