private protected override void CloneCore(TState state)
            {
                base.CloneCore(state);
                Contracts.Assert(state is AnomalyDetectionStateBase);
                var stateLocal = state as AnomalyDetectionStateBase;

                stateLocal.LogMartingaleUpdateBuffer = LogMartingaleUpdateBuffer.Clone();
                stateLocal.RawScoreBuffer            = RawScoreBuffer.Clone();
            }
            private protected sealed override void TransformCore(ref TInput input, FixedSizeQueue <TInput> windowedBuffer, long iteration, ref VBuffer <Double> dst)
            {
                var outputLength = Parent.OutputLength;

                Host.Assert(outputLength >= 2);

                var   result   = VBufferEditor.Create(ref dst, outputLength);
                float rawScore = 0;

                for (int i = 0; i < outputLength; ++i)
                {
                    result.Values[i] = Double.NaN;
                }

                // Step 1: Computing the raw anomaly score
                result.Values[1] = ComputeRawAnomalyScore(ref input, windowedBuffer, iteration);

                if (Double.IsNaN(result.Values[1]))
                {
                    result.Values[0] = 0;
                }
                else
                {
                    if (WindowSize > 0)
                    {
                        // Step 2: Computing the p-value score
                        rawScore = (float)result.Values[1];
                        if (Parent.ThresholdScore == AlertingScore.RawScore)
                        {
                            switch (Parent.Side)
                            {
                            case AnomalySide.Negative:
                                rawScore = (float)(-result.Values[1]);
                                break;

                            case AnomalySide.Positive:
                                break;

                            default:
                                rawScore = (float)Math.Abs(result.Values[1]);
                                break;
                            }
                        }
                        else
                        {
                            result.Values[2] = ComputeKernelPValue(rawScore);

                            switch (Parent.Side)
                            {
                            case AnomalySide.Negative:
                                result.Values[2] = 1 - result.Values[2];
                                break;

                            case AnomalySide.Positive:
                                break;

                            default:
                                result.Values[2] = Math.Min(result.Values[2], 1 - result.Values[2]);
                                break;
                            }

                            // Keeping the p-value in the safe range
                            if (result.Values[2] < SequentialAnomalyDetectionTransformBase <TInput, TState> .MinPValue)
                            {
                                result.Values[2] = SequentialAnomalyDetectionTransformBase <TInput, TState> .MinPValue;
                            }
                            else if (result.Values[2] > SequentialAnomalyDetectionTransformBase <TInput, TState> .MaxPValue)
                            {
                                result.Values[2] = SequentialAnomalyDetectionTransformBase <TInput, TState> .MaxPValue;
                            }

                            RawScoreBuffer.AddLast(rawScore);

                            // Step 3: Computing the martingale value
                            if (Parent.Martingale != MartingaleType.None && Parent.ThresholdScore == AlertingScore.MartingaleScore)
                            {
                                Double martingaleUpdate = 0;
                                switch (Parent.Martingale)
                                {
                                case MartingaleType.Power:
                                    martingaleUpdate = Parent.LogPowerMartigaleBettingFunc(result.Values[2], Parent.PowerMartingaleEpsilon);
                                    break;

                                case MartingaleType.Mixture:
                                    martingaleUpdate = Parent.LogMixtureMartigaleBettingFunc(result.Values[2]);
                                    break;
                                }

                                if (LogMartingaleUpdateBuffer.Count == 0)
                                {
                                    for (int i = 0; i < LogMartingaleUpdateBuffer.Capacity; ++i)
                                    {
                                        LogMartingaleUpdateBuffer.AddLast(martingaleUpdate);
                                    }
                                    _logMartingaleValue += LogMartingaleUpdateBuffer.Capacity * martingaleUpdate;
                                }
                                else
                                {
                                    _logMartingaleValue += martingaleUpdate;
                                    _logMartingaleValue -= LogMartingaleUpdateBuffer.PeekFirst();
                                    LogMartingaleUpdateBuffer.AddLast(martingaleUpdate);
                                }

                                result.Values[3] = Math.Exp(_logMartingaleValue);
                            }
                        }
                    }

                    // Generating alert
                    bool alert = false;

                    if (RawScoreBuffer.IsFull) // No alert until the buffer is completely full.
                    {
                        switch (Parent.ThresholdScore)
                        {
                        case AlertingScore.RawScore:
                            alert = rawScore >= Parent.AlertThreshold;
                            break;

                        case AlertingScore.PValueScore:
                            alert = result.Values[2] <= Parent.AlertThreshold;
                            break;

                        case AlertingScore.MartingaleScore:
                            alert = (Parent.Martingale != MartingaleType.None) && (result.Values[3] >= Parent.AlertThreshold);

                            if (alert)
                            {
                                if (_martingaleAlertCounter > 0)
                                {
                                    alert = false;
                                }
                                else
                                {
                                    _martingaleAlertCounter = Parent.WindowSize;
                                }
                            }

                            _martingaleAlertCounter--;
                            _martingaleAlertCounter = _martingaleAlertCounter < 0 ? 0 : _martingaleAlertCounter;
                            break;
                        }
                    }

                    result.Values[0] = Convert.ToDouble(alert);
                }

                dst = result.Commit();
            }