github.com/neugram/ng@v0.0.0-20180309130942-d472ff93d872/frame/memframe/memframe.go (about) 1 // Copyright 2015 The Neugram Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package memframe 6 7 import ( 8 "errors" 9 "fmt" 10 "io" 11 "math/big" 12 13 "neugram.io/ng/frame" 14 ) 15 16 /* 17 type Int struct { 18 Data []big.Int 19 Stride int 20 Rect Rectangle 21 } 22 23 type Float64 struct { 24 Data []float64 25 Stride int 26 Rect Rectangle 27 } 28 */ 29 30 type Memory struct { 31 ColName []string 32 //ColType []frame.Type TODO 33 Data []interface{} 34 Stride int 35 Width int 36 Height int 37 } 38 39 func New(width, height int) *Memory { 40 return &Memory{ 41 ColName: make([]string, width), 42 Data: make([]interface{}, width*height), 43 Stride: width, 44 Width: width, 45 Height: height, 46 } 47 } 48 49 func NewLiteral(colName []string, data [][]interface{}) *Memory { 50 d := New(len(colName), len(data)) 51 d.ColName = append([]string{}, colName...) 52 for i, row := range data { 53 if len(row) != len(colName) { 54 panic(fmt.Sprintf("memframe.NewLiteral: row %d length is %d, want %d", i, len(row), len(colName))) 55 } 56 copy(d.Data[i*d.Stride:], row) 57 } 58 return d 59 } 60 61 var errPtrNil = errors.New("pointer is nil") 62 63 func assign(dst, src interface{}) error { 64 if dst, ok := dst.(*interface{}); ok { 65 *dst = src 66 return nil 67 } 68 69 switch src := src.(type) { 70 case string: 71 switch dst := dst.(type) { 72 case *string: 73 if dst == nil { 74 return errPtrNil 75 } 76 *dst = src 77 return nil 78 } 79 // TODO case []byte? 80 case int: 81 switch dst := dst.(type) { 82 case *int: 83 if dst == nil { 84 return errPtrNil 85 } 86 *dst = src 87 return nil 88 case *int64: 89 if dst == nil { 90 return errPtrNil 91 } 92 *dst = int64(src) 93 return nil 94 case *big.Int: 95 if dst == nil { 96 return errPtrNil 97 } 98 dst.SetInt64(int64(src)) 99 return nil 100 } 101 case float64: 102 switch dst := dst.(type) { 103 case *float64: 104 if dst == nil { 105 return errPtrNil 106 } 107 *dst = src 108 return nil 109 case *big.Float: 110 if dst == nil { 111 return errPtrNil 112 } 113 dst.SetFloat64(src) 114 return nil 115 } 116 case complex128: 117 switch dst := dst.(type) { 118 case *complex128: 119 if dst == nil { 120 return errPtrNil 121 } 122 *dst = src 123 return nil 124 } 125 case *big.Int: 126 switch dst := dst.(type) { 127 case *big.Int: 128 if dst == nil { 129 return errPtrNil 130 } 131 dst.Set(src) 132 return nil 133 case *big.Float: 134 if dst == nil { 135 return errPtrNil 136 } 137 dst.SetInt(src) 138 return nil 139 } 140 case *big.Float: 141 switch dst := dst.(type) { 142 case *big.Float: 143 if dst == nil { 144 return errPtrNil 145 } 146 dst.Set(src) 147 return nil 148 } 149 case nil: 150 } 151 152 return fmt.Errorf("assign: dst:%T, src:%T\n", dst, src) 153 } 154 155 func (d *Memory) offset(x, y int) int { return y*d.Stride + x } 156 func (d *Memory) Get(x, y int, dst ...interface{}) error { 157 if y >= d.Height { 158 return io.EOF 159 } 160 for i, dst := range dst { 161 // TODO use frame.Type? 162 if err := assign(dst, d.Data[d.offset(x+i, y)]); err != nil { 163 return fmt.Errorf("memframe: Get(%d, %d, ... %d:%T): %v", x, y, i, dst, err) 164 } 165 } 166 return nil 167 } 168 169 func (d *Memory) Cols() []string { return d.ColName } 170 171 func (d *Memory) Len() (int, error) { return d.Height, nil } 172 173 func (d *Memory) Set(x, y int, vals ...interface{}) error { 174 if y >= d.Height { // Grow 175 data := make([]interface{}, d.Stride*(y+1)) 176 copy(data, d.Data) 177 d.Data = data 178 d.Height = y + 1 179 } 180 // TODO check for valid types 181 if len(vals)+x > d.Width { 182 return fmt.Errorf("memframe.Set(%d, y, len=%d) called for frame width %d", x, len(vals), d.Width) 183 } 184 copy(d.Data[d.offset(x, y):], vals) 185 return nil 186 } 187 188 func (d *Memory) Slice(x, xlen, y, ylen int) frame.Frame { 189 if ylen == -1 { 190 ylen = d.Height 191 } 192 return &Memory{ 193 ColName: d.ColName[x : x+xlen], 194 Data: d.Data[d.offset(x, y):], 195 Stride: d.Stride, 196 Width: xlen, 197 Height: ylen, 198 } 199 }