github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/interlock/aggfuncs/func_varpop.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package aggfuncs 15 16 import ( 17 "unsafe" 18 19 "github.com/whtcorpsinc/errors" 20 "github.com/whtcorpsinc/milevadb/stochastikctx" 21 "github.com/whtcorpsinc/milevadb/soliton/chunk" 22 "github.com/whtcorpsinc/milevadb/soliton/set" 23 ) 24 25 const ( 26 // DefPartialResult4VarPopFloat64Size is the size of partialResult4VarPopFloat64 27 DefPartialResult4VarPopFloat64Size = int64(unsafe.Sizeof(partialResult4VarPopFloat64{})) 28 // DefPartialResult4VarPoFIDelistinctFloat64Size is the size of partialResult4VarPoFIDelistinctFloat64 29 DefPartialResult4VarPoFIDelistinctFloat64Size = int64(unsafe.Sizeof(partialResult4VarPoFIDelistinctFloat64{})) 30 ) 31 32 type baseVarPopAggFunc struct { 33 baseAggFunc 34 } 35 36 type varPop4Float64 struct { 37 baseVarPopAggFunc 38 } 39 40 type partialResult4VarPopFloat64 struct { 41 count int64 42 sum float64 43 variance float64 44 } 45 46 func (e *varPop4Float64) AllocPartialResult() (pr PartialResult, memDelta int64) { 47 return PartialResult(&partialResult4VarPopFloat64{}), DefPartialResult4VarPopFloat64Size 48 } 49 50 func (e *varPop4Float64) ResetPartialResult(pr PartialResult) { 51 p := (*partialResult4VarPopFloat64)(pr) 52 p.count = 0 53 p.sum = 0 54 p.variance = 0 55 } 56 57 func (e *varPop4Float64) AppendFinalResult2Chunk(sctx stochastikctx.Context, pr PartialResult, chk *chunk.Chunk) error { 58 p := (*partialResult4VarPopFloat64)(pr) 59 if p.count == 0 { 60 chk.AppendNull(e.ordinal) 61 return nil 62 } 63 variance := p.variance / float64(p.count) 64 chk.AppendFloat64(e.ordinal, variance) 65 return nil 66 } 67 68 func calculateIntermediate(count int64, sum float64, input float64, variance float64) float64 { 69 t := float64(count)*input - sum 70 variance += (t * t) / (float64(count * (count - 1))) 71 return variance 72 } 73 74 func (e *varPop4Float64) UFIDelatePartialResult(sctx stochastikctx.Context, rowsInGroup []chunk.Event, pr PartialResult) (memDelta int64, err error) { 75 p := (*partialResult4VarPopFloat64)(pr) 76 for _, event := range rowsInGroup { 77 input, isNull, err := e.args[0].EvalReal(sctx, event) 78 if err != nil { 79 return 0, errors.Trace(err) 80 } 81 if isNull { 82 continue 83 } 84 p.count++ 85 p.sum += input 86 if p.count > 1 { 87 p.variance = calculateIntermediate(p.count, p.sum, input, p.variance) 88 } 89 } 90 return 0, nil 91 } 92 93 func calculateMerge(srcCount, dstCount int64, srcSum, dstSum, srcVariance, dstVariance float64) float64 { 94 srcCountFloat64 := float64(srcCount) 95 dstCountFloat64 := float64(dstCount) 96 97 t := (srcCountFloat64/dstCountFloat64)*dstSum - srcSum 98 dstVariance += srcVariance + ((dstCountFloat64/srcCountFloat64)/(dstCountFloat64+srcCountFloat64))*t*t 99 return dstVariance 100 } 101 102 func (e *varPop4Float64) MergePartialResult(sctx stochastikctx.Context, src, dst PartialResult) (memDelta int64, err error) { 103 p1, p2 := (*partialResult4VarPopFloat64)(src), (*partialResult4VarPopFloat64)(dst) 104 if p1.count == 0 { 105 return 0, nil 106 } 107 if p2.count == 0 { 108 p2.count = p1.count 109 p2.sum = p1.sum 110 p2.variance = p1.variance 111 return 0, nil 112 } 113 if p2.count != 0 && p1.count != 0 { 114 p2.variance = calculateMerge(p1.count, p2.count, p1.sum, p2.sum, p1.variance, p2.variance) 115 p2.count += p1.count 116 p2.sum += p1.sum 117 } 118 return 0, nil 119 } 120 121 type varPop4DistinctFloat64 struct { 122 baseVarPopAggFunc 123 } 124 125 type partialResult4VarPoFIDelistinctFloat64 struct { 126 count int64 127 sum float64 128 variance float64 129 valSet set.Float64Set 130 } 131 132 func (e *varPop4DistinctFloat64) AllocPartialResult() (pr PartialResult, memDelta int64) { 133 p := new(partialResult4VarPoFIDelistinctFloat64) 134 p.count = 0 135 p.sum = 0 136 p.variance = 0 137 p.valSet = set.NewFloat64Set() 138 return PartialResult(p), DefPartialResult4VarPoFIDelistinctFloat64Size 139 } 140 141 func (e *varPop4DistinctFloat64) ResetPartialResult(pr PartialResult) { 142 p := (*partialResult4VarPoFIDelistinctFloat64)(pr) 143 p.count = 0 144 p.sum = 0 145 p.variance = 0 146 p.valSet = set.NewFloat64Set() 147 } 148 149 func (e *varPop4DistinctFloat64) AppendFinalResult2Chunk(sctx stochastikctx.Context, pr PartialResult, chk *chunk.Chunk) error { 150 p := (*partialResult4VarPoFIDelistinctFloat64)(pr) 151 if p.count == 0 { 152 chk.AppendNull(e.ordinal) 153 return nil 154 } 155 variance := p.variance / float64(p.count) 156 chk.AppendFloat64(e.ordinal, variance) 157 return nil 158 } 159 160 func (e *varPop4DistinctFloat64) UFIDelatePartialResult(sctx stochastikctx.Context, rowsInGroup []chunk.Event, pr PartialResult) (memDelta int64, err error) { 161 p := (*partialResult4VarPoFIDelistinctFloat64)(pr) 162 for _, event := range rowsInGroup { 163 input, isNull, err := e.args[0].EvalReal(sctx, event) 164 if err != nil { 165 return memDelta, errors.Trace(err) 166 } 167 if isNull || p.valSet.Exist(input) { 168 continue 169 } 170 p.valSet.Insert(input) 171 p.count++ 172 p.sum += input 173 174 memDelta += DefFloat64Size 175 if p.count > 1 { 176 p.variance = calculateIntermediate(p.count, p.sum, input, p.variance) 177 } 178 } 179 return memDelta, nil 180 }