github.com/wzzhu/tensor@v0.9.24/genlib2/generic_reduce.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io" 6 "text/template" 7 ) 8 9 const reflectBasedReduceRaw = `func ReduceRef(f reflect.Value, fnT reflect.Type, def reflect.Value, l *Dense) interface{} { 10 retVal := def 11 if l.len() == 0 { 12 return retVal.Interface() 13 } 14 15 args := make([]reflect.Value, 0, fnT.NumIn()) 16 for i := 0; i < l.len(); i++ { 17 v := reflect.ValueOf(l.Get(i)) 18 args = append(args, retVal) 19 args = append(args, v) 20 retVal = f.Call(args)[0] 21 args = args[:0] 22 } 23 return retVal.Interface() 24 } 25 26 ` 27 const genericReduceRaw = `func Reduce{{short .}}(f func(a, b {{asType .}}) {{asType .}}, def {{asType .}}, l ...{{asType .}}) (retVal {{asType .}}){ 28 retVal = def 29 if len(l) == 0 { 30 return 31 } 32 33 for _, v := range l { 34 retVal = f(retVal, v) 35 } 36 return 37 } 38 39 ` 40 41 const genericSumRaw = `func Sum{{short .}}(a []{{asType .}}) {{asType .}}{ 42 var retVal {{asType .}} 43 a = a[:len(a)] 44 for _, v := range a { 45 retVal += v 46 } 47 return retVal 48 } 49 ` 50 51 const genericProdRaw = `func Prod{{short .}}(a []{{asType .}}) {{asType .}} { 52 if len(a) == 0 { 53 return 0 54 } 55 var retVal {{asType .}} = 1 56 a = a[:len(a)] 57 for _, v := range a { 58 retVal *= v 59 } 60 return retVal 61 } 62 ` 63 64 const genericSliceMinMaxRaw = `func SliceMin{{short .}}(a []{{asType .}}) {{asType .}}{ 65 if len(a) < 1 { 66 panic("Max of empty slice is meaningless") 67 } 68 return Reduce{{short .}}(Min{{short .}}, a[0], a[1:]...) 69 } 70 71 func SliceMax{{short .}}(a []{{asType .}}) {{asType .}}{ 72 if len(a) < 1 { 73 panic("Max of empty slice is meaningless") 74 } 75 return Reduce{{short .}}(Max{{short .}}, a[0], a[1:]...) 76 } 77 78 ` 79 80 const genericReduce0Raw = `func reduceFirst{{short .}}(data, retVal []{{asType .}}, split, size int, fn func(a, b []{{asType .}})) { 81 start := split 82 copy(retVal[0:split], data[0:split]) 83 for i := 0; i < size - 1; i++ { 84 fn(retVal, data[start:start+split]) 85 start += split 86 } 87 } 88 89 func genericReduceFirst{{short .}}(data, retVal []{{asType .}}, split, size int, fn func(a, b {{asType .}}){{asType .}} ){ 90 start := split 91 copy(retVal[0:split], data[0:split]) 92 for i := 0; i < size - 1; i++ { 93 for j := 0; j < split; j++ { 94 retVal[j] = fn(retVal[j], data[j+start]) 95 } 96 start += split 97 } 98 } 99 ` 100 101 const genericReduce0ParRaw = `func reduceFirst{{short .}}(data, retVal []{{asType .}}, split, size int, fn func(a, b {{asType .}}){{asType .}}) { 102 start := split 103 var wg sync.Waitgroup 104 for i := 0; i < size - 1; i++ { 105 wg.Add(1) 106 go func(sp, st int) { 107 for j := 0; j < sp; j++ { 108 retVal[j] = fn(retVal[j], data[j+start]) 109 } 110 }(split, start, &wg) 111 start += split 112 } 113 } 114 115 ` 116 117 const genericReduceLastRaw = `func reduceLast{{short .}}(a, retVal []{{asType .}}, dimSize int, defaultValue {{asType .}}, fn func(a []{{asType .}}){{asType .}}) { 118 var at int 119 for start := 0; start <= len(a) - dimSize; start += dimSize { 120 r := fn(a[start:start+dimSize]) 121 retVal[at] = r 122 at++ 123 } 124 } 125 126 func genericReduceLast{{short .}}(a, retVal []{{asType .}}, dimSize int, defaultValue {{asType .}}, fn func({{asType .}}, {{asType .}}){{asType .}}) { 127 var at int 128 for start := 0; start <= len(a) - dimSize; start += dimSize { 129 r := Reduce{{short .}}(fn, defaultValue, a[start:start+dimSize]...) 130 retVal[at] = r 131 at++ 132 } 133 } 134 135 ` 136 137 const genericReduceDefaultRaw = `func reduceDefault{{short .}}(data, retVal []{{asType .}}, dim0, dimSize, outerStride, stride, expected int, fn func(a,b {{asType .}}){{asType .}}) { 138 for i := 0; i < dim0; i++ { 139 start := i * outerStride 140 sliced := data[start : start+outerStride] 141 var innerStart, strideTrack int 142 for j := 0; j < expected; j++ { 143 writeTo := i * expected + j 144 retVal[writeTo] = sliced[innerStart] 145 for k := 1; k < dimSize; k++ { 146 readFrom := innerStart + k * stride 147 retVal[writeTo] = fn(retVal[writeTo], sliced[readFrom]) 148 } 149 strideTrack++ 150 if strideTrack >= stride { 151 strideTrack = 0 152 innerStart += stride 153 } 154 innerStart++ 155 } 156 } 157 } 158 159 ` 160 161 var ( 162 genericReduce *template.Template 163 genericSum *template.Template 164 genericProd *template.Template 165 genericSliceMinMax *template.Template 166 167 genericReduce0 *template.Template 168 genericReduceLast *template.Template 169 genericReduceDefault *template.Template 170 ) 171 172 func init() { 173 genericReduce = template.Must(template.New("genericReduce").Funcs(funcs).Parse(genericReduceRaw)) 174 genericSum = template.Must(template.New("genericSum").Funcs(funcs).Parse(genericSumRaw)) 175 genericProd = template.Must(template.New("genericProd").Funcs(funcs).Parse(genericProdRaw)) 176 genericSliceMinMax = template.Must(template.New("genericSliceMinMax").Funcs(funcs).Parse(genericSliceMinMaxRaw)) 177 genericReduce0 = template.Must(template.New("genericReduce0").Funcs(funcs).Parse(genericReduce0Raw)) 178 genericReduceLast = template.Must(template.New("genericReduceLast").Funcs(funcs).Parse(genericReduceLastRaw)) 179 genericReduceDefault = template.Must(template.New("genericReduceDefault").Funcs(funcs).Parse(genericReduceDefaultRaw)) 180 } 181 182 func generateGenericReduce(f io.Writer, generic Kinds) { 183 // fmt.Fprintln(f, reflectBasedReduceRaw) 184 for _, k := range generic.Kinds { 185 if !isParameterized(k) { 186 genericReduce.Execute(f, k) 187 } 188 } 189 190 for _, k := range filter(generic.Kinds, isNumber) { 191 genericSum.Execute(f, k) 192 193 } 194 for _, k := range filter(generic.Kinds, isNumber) { 195 genericProd.Execute(f, k) 196 } 197 fmt.Fprintf(f, "\n") 198 199 for _, k := range filter(generic.Kinds, isOrd) { 200 if isNumber(k) { 201 genericSliceMinMax.Execute(f, k) 202 } 203 } 204 205 for _, k := range filter(generic.Kinds, isNotParameterized) { 206 genericReduce0.Execute(f, k) 207 } 208 209 for _, k := range filter(generic.Kinds, isNotParameterized) { 210 genericReduceLast.Execute(f, k) 211 } 212 213 for _, k := range filter(generic.Kinds, isNotParameterized) { 214 genericReduceDefault.Execute(f, k) 215 } 216 }