示例#1
0
        public void CouldCalculateSMAWithWidthEQ()
        {
            Assert.Throws <NotImplementedException>(() =>
            {
                var count = 20;
                var sm    = new SortedMap <int, double>();
                sm.Add(0, 0);
                for (int i = 2; i <= count; i++)
                {
                    sm.Add(i, i);
                }
                sm.Remove(11);
                sm.Remove(12);
                var onlineOp = new SumAvgOnlineOp <int, double, SortedMapCursor <int, double> >();
                var smaOp    = new SpanOpWidth <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >
                                   (2, Lookup.EQ, onlineOp);
                var smaSeries =
                    new SpanOpImpl <int,
                                    double,
                                    double,
                                    SpanOpWidth <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >,
                                    SortedMapCursor <int, double>
                                    >(sm.GetEnumerator(), smaOp).Source;

                foreach (var keyValuePair in smaSeries)
                {
                    Trace.WriteLine($"{keyValuePair.Key} - {keyValuePair.Value}");
                }
            });
        }
示例#2
0
        internal Stat2Cursor(TCursor cursor, TKey width, Lookup lookup) : this()
        {
            var op     = new Stat2OnlineOp <TKey, TValue, TCursor>();
            var spanOp =
                new SpanOp <TKey, TValue, Stat2 <TKey>,
                            TCursor, Stat2OnlineOp <TKey, TValue, TCursor> >(width, lookup, op, cursor.Comparer);

            _cursor =
                new SpanOpImpl <TKey, TValue,
                                Stat2 <TKey>,
                                SpanOp <TKey, TValue, Stat2 <TKey>, TCursor, Stat2OnlineOp <TKey, TValue, TCursor>
                                        >,
                                TCursor
                                >(cursor, spanOp);
        }
示例#3
0
        public bool TryGetValue(TKey key, out Stat2 <TKey> value)
        {
            if (_lookUpCursor.Equals(default(TCursor)))
            {
                _lookUpCursor = _cursor.Clone();
            }

            if (_lookUpCursor.MoveAt(key, Lookup.EQ))
            {
                value = _lookUpCursor.CurrentValue;
                return(true);
            }

            value = default;
            return(false);
        }
示例#4
0
        public bool TryGetValue(TKey key, out Series <TKey, TValue, Range <TKey, TValue, TCursor> > value)
        {
            if (_lookUpCursor.Equals(default(TCursor)))
            {
                _lookUpCursor = _cursor.Clone();
            }

            if (_lookUpCursor.MoveAt(key, Lookup.EQ))
            {
                value = _lookUpCursor.CurrentValue.Source;
                return(true);
            }

            value = default;
            return(false);
        }
示例#5
0
        internal Window(TCursor cursor, TKey width, Lookup lookup) : this()
        {
            if (cursor.IsIndexed)
            {
                throw new NotSupportedException("Window is not supported for indexed series, only for sorted ones.");
            }
            var op     = new WindowOnlineOp <TKey, TValue, TCursor>();
            var spanOp =
                new SpanOp <TKey, TValue, Range <TKey, TValue, TCursor>,
                            TCursor, WindowOnlineOp <TKey, TValue, TCursor> >(width, lookup, op, cursor.Comparer);

            _cursor =
                new SpanOpImpl <TKey, TValue,
                                Range <TKey, TValue, TCursor>,
                                SpanOp <TKey, TValue, Range <TKey, TValue, TCursor>, TCursor, WindowOnlineOp <TKey, TValue, TCursor>
                                        >,
                                TCursor
                                >(cursor, spanOp);
        }
示例#6
0
        internal Stat2Cursor(TCursor cursor, int width = 1, bool allowIncomplete = false) : this()
        {
            if (width <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(width));
            }

            var op     = new Stat2OnlineOp <TKey, TValue, TCursor>();
            var spanOp =
                new SpanOp <TKey, TValue, Stat2 <TKey>,
                            TCursor, Stat2OnlineOp <TKey, TValue, TCursor> >(width, allowIncomplete, op, cursor.Comparer);

            _cursor =
                new SpanOpImpl <TKey, TValue,
                                Stat2 <TKey>,
                                SpanOp <TKey, TValue, Stat2 <TKey>, TCursor, Stat2OnlineOp <TKey, TValue, TCursor>
                                        >,
                                TCursor
                                >(cursor, spanOp);
        }
示例#7
0
        internal Window(TCursor cursor, int count, bool allowIncomplete = false) : this()
        {
            if (cursor.IsIndexed)
            {
                throw new NotSupportedException("Window is not supported for indexed series, only for sorted ones.");
            }
            if (count <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(count));
            }

            var op     = new WindowOnlineOp <TKey, TValue, TCursor>();
            var spanOp =
                new SpanOp <TKey, TValue, Range <TKey, TValue, TCursor>,
                            TCursor, WindowOnlineOp <TKey, TValue, TCursor> >(count, allowIncomplete, op, cursor.Comparer);

            _cursor =
                new SpanOpImpl <TKey, TValue,
                                Range <TKey, TValue, TCursor>,
                                SpanOp <TKey, TValue, Range <TKey, TValue, TCursor>, TCursor, WindowOnlineOp <TKey, TValue, TCursor>
                                        >,
                                TCursor
                                >(cursor, spanOp);
        }
示例#8
0
        public void WindowDirectAndIndirectSpanOpBenchmark()
        {
            Settings.DoAdditionalCorrectnessChecks = false;

            var count = 100000;
            var width = 20;
            var sm    = new SortedMap <int, double>();

            sm.Add(0, 0); // make irregular, it's faster but more memory
            for (int i = 2; i <= count; i++)
            {
                sm.Add(i, i);
            }

            var op     = new WindowOnlineOp <int, double, SortedMapCursor <int, double> >();
            var spanOp =
                new SpanOpCount <int, double, Range <int, double, SortedMapCursor <int, double> >,
                                 SortedMapCursor <int, double>, WindowOnlineOp <int, double, SortedMapCursor <int, double> > >(20, false,
                                                                                                                               op);
            var window =
                new SpanOpImpl <int,
                                double,
                                Range <int, double, SortedMapCursor <int, double> >,
                                SpanOpCount <int, double, Range <int, double, SortedMapCursor <int, double> >, SortedMapCursor <int, double>, WindowOnlineOp <int, double, SortedMapCursor <int, double> > >,
                                SortedMapCursor <int, double>
                                >(sm.GetEnumerator(), spanOp).Source
                .Map(x =>
            {
                var sum = 0.0;
                var c   = 0;
                foreach (var keyValuePair in x.Source)
                {
                    sum += keyValuePair.Value;
                    c++;
                }
                return(sum / c);        // x.CursorDefinition.Count TODO
            });

            var spanOpCombined =
                new SpanOp <int, double, Range <int, double, SortedMapCursor <int, double> >,
                            SortedMapCursor <int, double>, WindowOnlineOp <int, double, SortedMapCursor <int, double> > >(20, false,
                                                                                                                          op, sm.comparer);
            var windowCombined =
                new SpanOpImpl <int,
                                double,
                                Range <int, double, SortedMapCursor <int, double> >,
                                SpanOp <int, double, Range <int, double, SortedMapCursor <int, double> >, SortedMapCursor <int, double>, WindowOnlineOp <int, double, SortedMapCursor <int, double> > >,
                                SortedMapCursor <int, double>
                                >(sm.GetEnumerator(), spanOpCombined).Source
                .Map(x =>
            {
                var sum = 0.0;
                var c   = 0;
                foreach (var keyValuePair in x.Source)
                {
                    sum += keyValuePair.Value;
                    c++;
                }
                return(sum / c);    // x.CursorDefinition.Count TODO
            });

            var windowExtension = sm.Window(width).Map(x =>
            {
                var sum = 0.0;
                var c   = 0;
                foreach (var keyValuePair in x)
                {
                    sum += keyValuePair.Value;
                    c++;
                }
                return(sum / c); // x.CursorDefinition.Count TODO
            });

            for (int round = 0; round < 20; round++)
            {
                double sum1 = 0.0;
                using (Benchmark.Run("Window SpanOpCount", count * width))
                {
                    foreach (var keyValuePair in window)
                    {
                        sum1 += keyValuePair.Value;
                    }
                }

                double sum2 = 0.0;
                using (Benchmark.Run("Window SpanOp", count * width))
                {
                    foreach (var keyValuePair in windowCombined)
                    {
                        sum2 += keyValuePair.Value;
                    }
                }

                double sum3 = 0.0;
                using (Benchmark.Run("Window Extension", count * width))
                {
                    foreach (var keyValuePair in windowExtension)
                    {
                        sum3 += keyValuePair.Value;
                    }
                }

                Assert.AreEqual(sum1, sum2);
                Assert.AreEqual(sum1, sum3);
            }

            Benchmark.Dump($"The window width is {width}.");
        }
示例#9
0
        public void SMADirectAndIndirectSpanOpBenchmark()
        {
            Settings.DoAdditionalCorrectnessChecks = false;

            var count = 1000000;
            var width = 20;
            var sm    = new SortedMap <int, double>();

            sm.Add(0, 0); // make irregular, it's faster but more memory
            for (int i = 2; i <= count; i++)
            {
                sm.Add(i, i);
            }

            var directSMA =
                new SpanOpImpl <int,
                                double,
                                double,
                                MAvgCount <int, double, SortedMapCursor <int, double> >,
                                SortedMapCursor <int, double>
                                >(sm.GetEnumerator(), new MAvgCount <int, double, SortedMapCursor <int, double> >(width, false)).Source;

            var indirectSma =
                new SpanOpImpl <int,
                                double,
                                double,
                                SpanOpCount <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >,
                                SortedMapCursor <int, double>
                                >(sm.GetEnumerator(),
                                  new SpanOpCount <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >(width, false, new SumAvgOnlineOp <int, double, SortedMapCursor <int, double> >())).Source;

            var indirectSmaCombined =
                new SpanOpImpl <int,
                                double,
                                double,
                                SpanOp <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >,
                                SortedMapCursor <int, double>
                                >(sm.GetEnumerator(),
                                  new SpanOp <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >(width, false, new SumAvgOnlineOp <int, double, SortedMapCursor <int, double> >(), sm.comparer)).Source;

            var extensionSma = sm.SMA(width);

            var windowSma = sm.Window(width).Map(x =>
            {
                var sum = 0.0;
                var c   = 0;
                foreach (var keyValuePair in x)
                {
                    sum += keyValuePair.Value;
                    c++;
                }
                return(sum / c); // x.CursorDefinition.Count TODO
            });

            for (int round = 0; round < 20; round++)
            {
                double sum1 = 0.0;
                using (Benchmark.Run("SMA Direct", count * width))
                {
                    foreach (var keyValuePair in directSMA)
                    {
                        sum1 += keyValuePair.Value;
                    }
                }

                double sum2 = 0.0;
                using (Benchmark.Run("SMA Indirect", count * width))
                {
                    foreach (var keyValuePair in indirectSma)
                    {
                        sum2 += keyValuePair.Value;
                    }
                }

                double sum2_2 = 0.0;
                using (Benchmark.Run("SMA Indirect Combined", count * width))
                {
                    foreach (var keyValuePair in indirectSmaCombined)
                    {
                        sum2_2 += keyValuePair.Value;
                    }
                }

                double sum2_3 = 0.0;
                using (Benchmark.Run("SMA Extension", count * width))
                {
                    foreach (var keyValuePair in extensionSma)
                    {
                        sum2_3 += keyValuePair.Value;
                    }
                }

                double sum3 = 0.0;
                using (Benchmark.Run("SMA Window", count * width))
                {
                    foreach (var keyValuePair in windowSma)
                    {
                        sum3 += keyValuePair.Value;
                    }
                }

                var sumxx = 0.0;
                using (Benchmark.Run("SortedMap", count))
                {
                    foreach (var keyValuePair in sm)
                    {
                        sumxx += keyValuePair.Value;
                    }
                }

                Assert.AreEqual(sum1, sum2);
                Assert.AreEqual(sum1, sum2_2);
                Assert.AreEqual(sum1, sum2_3);
                Assert.AreEqual(sum1, sum3);
            }

            Benchmark.Dump($"The window width is {width}. SMA MOPS are calculated as a number of calculated values multiplied by width, " +
                           $"which is equivalent to the total number of cursor moves for Window case. SortedMap line is for reference - it is the " +
                           $"speed of raw iteration over SM without Windows overheads.");
        }
示例#10
0
        public void CouldCalculateSMAWithWidth()
        {
            var count = 20;
            var sm    = new SortedMap <int, double>();

            for (int i = 1; i <= count; i++)
            {
                sm.Add(i, i);
            }

            DoTest(Lookup.EQ);
            DoTest(Lookup.GE);
            DoTest(Lookup.GT);
            DoTest(Lookup.LE);
            DoTest(Lookup.LT);

            DoTestViaSpanOpWidth(Lookup.EQ);
            DoTestViaSpanOpWidth(Lookup.GE);
            DoTestViaSpanOpWidth(Lookup.GT);
            DoTestViaSpanOpWidth(Lookup.LE);
            DoTestViaSpanOpWidth(Lookup.LT);

            void DoTest(Lookup lookup)
            {
                // width 9 is the same as count = 10 for the regular int series
                var smaOp     = new MAvgWidth <int, double, SortedMapCursor <int, double> >(9, lookup);
                var smaCursor =
                    new SpanOpImpl <int,
                                    double,
                                    double,
                                    MAvgWidth <int, double, SortedMapCursor <int, double> >,
                                    SortedMapCursor <int, double>
                                    >(sm.GetEnumerator(), smaOp);

                // this monster type must be hidden in the same way Lag hides its implementation
                Series <int, double, SpanOpImpl <int, double, double, MAvgWidth <int, double, SortedMapCursor <int, double> >, SortedMapCursor <int, double> > > smaSeries;

                smaSeries = smaCursor.Source;

                var sm2 = smaSeries.ToSortedMap();

                Assert.AreEqual(sm2.First, smaSeries.First);
                Assert.AreEqual(sm2.Last, smaSeries.Last);

                Assert.True(SeriesContract.MoveAtShouldWorkOnLazySeries(smaSeries));
                Assert.True(SeriesContract.ClonedCursorsAreIndependent(smaSeries));

                if (lookup == Lookup.EQ || lookup == Lookup.GE)
                {
                    var trueSma = sm.Window(10).Map(x => x.Values.Average());
                    Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys));
                    Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values));
                }

                if (lookup == Lookup.GT)
                {
                    var trueSma = sm.Window(11).Map(x => x.Values.Average());
                    Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys));
                    Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values));
                }

                if (lookup == Lookup.LE)
                {
                    var smaOp1  = new MAvgCount <int, double, SortedMapCursor <int, double> >(10, true);
                    var trueSma =
                        new SpanOpImpl <int,
                                        double,
                                        double,
                                        MAvgCount <int, double, SortedMapCursor <int, double> >,
                                        SortedMapCursor <int, double>
                                        >(sm.GetEnumerator(), smaOp1).Source;

                    Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys));
                    Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values));
                }

                if (lookup == Lookup.LT)
                {
                    var smaOp1  = new MAvgCount <int, double, SortedMapCursor <int, double> >(9, true);
                    var trueSma =
                        new SpanOpImpl <int,
                                        double,
                                        double,
                                        MAvgCount <int, double, SortedMapCursor <int, double> >,
                                        SortedMapCursor <int, double>
                                        >(sm.GetEnumerator(), smaOp1).Source;

                    Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys));
                    Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values));
                }

                Debug.WriteLine("SMA");
                foreach (var keyValuePair in smaSeries)
                {
                    Debug.WriteLine($"{keyValuePair.Key} - {keyValuePair.Value}");
                }
            }

            void DoTestViaSpanOpWidth(Lookup lookup)
            {
                // width 9 is the same as count = 10 for the regular int series

                var onlineOp  = new SumAvgOnlineOp <int, double, SortedMapCursor <int, double> >();
                var smaOp     = new SpanOpWidth <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >(9, lookup, onlineOp);
                var smaCursor =
                    new SpanOpImpl <int,
                                    double,
                                    double,
                                    SpanOpWidth <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >,
                                    SortedMapCursor <int, double>
                                    >(sm.GetEnumerator(), smaOp);

                // this monster type must be hidden in the same way Lag hides its implementation

                Series <int, double, SpanOpImpl <int, double, double, SpanOpWidth <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >, SortedMapCursor <int, double> > > smaSeries;

                smaSeries = smaCursor.Source;

                var sm2 = smaSeries.ToSortedMap();

                Assert.AreEqual(sm2.First, smaSeries.First);
                Assert.AreEqual(sm2.Last, smaSeries.Last);

                Assert.True(SeriesContract.MoveAtShouldWorkOnLazySeries(smaSeries));
                Assert.True(SeriesContract.ClonedCursorsAreIndependent(smaSeries));

                if (lookup == Lookup.EQ || lookup == Lookup.GE)
                {
                    var trueSma = sm.Window(10).Map(x => x.Values.Average());
                    Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys));
                    Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values));
                }

                if (lookup == Lookup.GT)
                {
                    var trueSma = sm.Window(11).Map(x => x.Values.Average());
                    Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys));
                    Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values));
                }

                if (lookup == Lookup.LE)
                {
                    var smaOp1  = new MAvgCount <int, double, SortedMapCursor <int, double> >(10, true);
                    var trueSma =
                        new SpanOpImpl <int,
                                        double,
                                        double,
                                        MAvgCount <int, double, SortedMapCursor <int, double> >,
                                        SortedMapCursor <int, double>
                                        >(sm.GetEnumerator(), smaOp1).Source;

                    Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys));
                    Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values));
                }

                if (lookup == Lookup.LT)
                {
                    var smaOp1  = new MAvgCount <int, double, SortedMapCursor <int, double> >(9, true);
                    var trueSma =
                        new SpanOpImpl <int,
                                        double,
                                        double,
                                        MAvgCount <int, double, SortedMapCursor <int, double> >,
                                        SortedMapCursor <int, double>
                                        >(sm.GetEnumerator(), smaOp1).Source;

                    Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys));
                    Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values));
                }

                Debug.WriteLine("SMA");
                foreach (var keyValuePair in smaSeries)
                {
                    Debug.WriteLine($"{keyValuePair.Key} - {keyValuePair.Value}");
                }
            }
        }
示例#11
0
        public void CouldCalculateSMAWithCount()
        {
            var count = 20;
            var sm    = new SortedMap <int, double>();

            for (int i = 1; i <= count; i++)
            {
                sm.Add(i, i);
            }

            DoTest(true);
            DoTest(false);

            DoTestViaSpanOpCount(true);
            DoTestViaSpanOpCount(false);

            void DoTest(bool allowIncomplete)
            {
                // TODO separate tests/cases for true/false
                var smaOp     = new MAvgCount <int, double, SortedMapCursor <int, double> >(10, allowIncomplete);
                var smaCursor =
                    new SpanOpImpl <int,
                                    double,
                                    double,
                                    MAvgCount <int, double, SortedMapCursor <int, double> >,
                                    SortedMapCursor <int, double>
                                    >(sm.GetEnumerator(), smaOp);

                // this monster type must be hidden in the same way Lag hides its implementation
                Series <int, double, SpanOpImpl <int, double, double, MAvgCount <int, double, SortedMapCursor <int, double> >, SortedMapCursor <int, double> > > smaSeries;

                smaSeries = smaCursor.Source;

                var sm2 = smaSeries.ToSortedMap();

                Assert.AreEqual(sm2.First, smaSeries.First);
                Assert.AreEqual(sm2.Last, smaSeries.Last);

                Assert.True(SeriesContract.MoveAtShouldWorkOnLazySeries(smaSeries));
                Assert.True(SeriesContract.ClonedCursorsAreIndependent(smaSeries));

                if (!allowIncomplete)
                {
                    var trueSma = sm.Window(10).Map(x => x.Values.Average());
                    Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys));
                    Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values));
                }

                Debug.WriteLine("SMA");
                foreach (var keyValuePair in smaSeries)
                {
                    Debug.WriteLine($"{keyValuePair.Key} - {keyValuePair.Value}");
                }
            }

            void DoTestViaSpanOpCount(bool allowIncomplete)
            {
                // TODO separate tests/cases for true/false
                var onlineOp  = new SumAvgOnlineOp <int, double, SortedMapCursor <int, double> >();
                var smaOp     = new SpanOpCount <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >(10, allowIncomplete, onlineOp);
                var smaCursor =
                    new SpanOpImpl <int,
                                    double,
                                    double,
                                    SpanOpCount <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >,
                                    SortedMapCursor <int, double>
                                    >(sm.GetEnumerator(), smaOp);

                // this monster type must be hidden in the same way Lag hides its implementation
                Series <int, double, SpanOpImpl <int, double, double, SpanOpCount <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >, SortedMapCursor <int, double> > > smaSeries;

                smaSeries = smaCursor.Source;

                var sm2 = smaSeries.ToSortedMap();

                Assert.AreEqual(sm2.First, smaSeries.First);
                Assert.AreEqual(sm2.Last, smaSeries.Last);

                Assert.True(SeriesContract.MoveAtShouldWorkOnLazySeries(smaSeries));
                Assert.True(SeriesContract.ClonedCursorsAreIndependent(smaSeries));

                if (!allowIncomplete)
                {
                    var trueSma = sm.Window(10).Map(x => x.Values.Average());
                    Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys));
                    Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values));
                }

                Debug.WriteLine("SMA");
                foreach (var keyValuePair in smaSeries)
                {
                    Debug.WriteLine($"{keyValuePair.Key} - {keyValuePair.Value}");
                }
            }
        }