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  }