public static PlotModel OxyPlot <G, M, RF>(this IDensity <G, M, RF> d, string title = null)
            where G :
        IBaseStructure <M>,
        IRealEmbedding <M, RF>
            where M :
        struct
            where RF :
        struct
        {
            var oxyplotter = new OxyPlotter <G, M, RealFieldType <RF>, RF>(d.BaseStructure, new RealFieldType <RF>());
            var rf         = d.RealField;

            title = title ?? d.GetTrimmedName();
            // TODO: For Expected() and Stdev() much more assumptions are necessary!
            // var subtitle = string.Format(
            //     CultureInfo.InvariantCulture,
            //     "Expected = {0:0.0000}, Stdev = {1:0.00}",
            //     d.Expected(),
            //     d.Stdev()
            // );
            var subtitle  = "";
            var plotModel = oxyplotter.GetPlot(
                k => d[k],
                d.SortedKeys(),
                title: title,
                subtitle: subtitle,
                yMin: rf.EmbedFromReal(0.0),
                valueLabelFormatter: p => rf.EmbedToReal(p).ToString("P", CultureInfo.InvariantCulture));

            return(plotModel);
        }
        public static void SaveOxyPlotPdf <G, M, RF>(this IDensity <G, M, RF> d, string filename = null)
            where G :
        IBaseStructure <M>,
        IRealEmbedding <M, RF>
            where M :
        struct
            where RF :
        struct
        {
            filename = filename ?? d.GetTrimmedName() + ".pdf";
            var oxyplot = d.OxyPlot(Path.GetFileName(filename));

            using (var stream = File.Create(filename))
            {
                var pdfExporter = new PdfExporter {
                    Width = 600, Height = 400
                };
                pdfExporter.Export(oxyplot, stream);
            }
        }
        public static IDensity <G, M, RF> ArithMult <G, M, RF>(this IDensity <G, M, RF> d, int n)
            where G :
        IAdditiveMonoid <M>
        {
            if (n < 0)
            {
                throw new ArgumentException();
            }
            if (n == 0)
            {
                return(new Zero <G, M, RF>(d.BaseStructure, d.RealField));
            }
            var newDensity = d;

            foreach (var step in Enumerable.Range(1, n - 1))
            {
                newDensity = newDensity.Add(d);
            }
            newDensity.Name = $"({d.GetTrimmedName()}).ArithMult({n})";
            return(newDensity);
        }
        public static IDensity <G, M, RF> ArithMult <G, M, RF>(this IDensity <G, M, RF> d, Density <int> dInt)
            where G :
        IAdditiveMonoid <M>
        {
            var resDict = new Dictionary <M, RF>();
            var rf      = d.RealField;

            foreach (var key in dInt.GetKeys())
            {
                var mulDensity = d.ArithMult(key);
                foreach (var mulKey in mulDensity.GetKeys())
                {
                    if (!resDict.ContainsKey(mulKey))
                    {
                        resDict[mulKey] = default(RF);
                    }
                    resDict[mulKey] = rf.Add(resDict[mulKey], rf.Multiply(mulDensity[mulKey], rf.EmbedFromReal(dInt[key])));
                }
            }
            var newDensity = new Density <G, M, RF>(resDict, d.BaseStructure, d.RealField, $"{d.GetTrimmedName()}.ArithMult({dInt.GetTrimmedName()})");

            return(newDensity);
        }