Probably done for today. Added a start to some caching optimizations.
This commit is contained in:
parent
48476dde69
commit
21c498f445
32
Base/Extensions/FormattingExtensions.cs
Normal file
32
Base/Extensions/FormattingExtensions.cs
Normal file
@ -0,0 +1,32 @@
|
||||
namespace Graphing.Extensions;
|
||||
|
||||
public static class FormattingExtensions
|
||||
{
|
||||
private static readonly string[] sizeUnits =
|
||||
[
|
||||
" bytes",
|
||||
" KB",
|
||||
" MB",
|
||||
" GB",
|
||||
" TB",
|
||||
" PB",
|
||||
];
|
||||
|
||||
public static string FormatAsBytes(this long bytes)
|
||||
{
|
||||
double val = bytes;
|
||||
int unitIndex = 0;
|
||||
|
||||
while (val > 1024)
|
||||
{
|
||||
unitIndex++;
|
||||
val /= 1024;
|
||||
}
|
||||
|
||||
string result;
|
||||
if (unitIndex == 0) result = val.ToString("0");
|
||||
else result = val.ToString("0.00");
|
||||
|
||||
return result + sizeUnits[unitIndex];
|
||||
}
|
||||
}
|
||||
20
Base/Forms/GraphForm.Designer.cs
generated
20
Base/Forms/GraphForm.Designer.cs
generated
@ -39,6 +39,8 @@
|
||||
MenuEquations = new ToolStripMenuItem();
|
||||
MenuEquationsDerivative = new ToolStripMenuItem();
|
||||
MenuEquationsIntegral = new ToolStripMenuItem();
|
||||
MenuMisc = new ToolStripMenuItem();
|
||||
MenuMiscCaches = new ToolStripMenuItem();
|
||||
GraphMenu.SuspendLayout();
|
||||
SuspendLayout();
|
||||
//
|
||||
@ -58,7 +60,7 @@
|
||||
// GraphMenu
|
||||
//
|
||||
GraphMenu.ImageScalingSize = new Size(32, 32);
|
||||
GraphMenu.Items.AddRange(new ToolStripItem[] { MenuViewport, MenuColors, MenuEquations });
|
||||
GraphMenu.Items.AddRange(new ToolStripItem[] { MenuViewport, MenuColors, MenuEquations, MenuMisc });
|
||||
GraphMenu.Location = new Point(0, 0);
|
||||
GraphMenu.Name = "GraphMenu";
|
||||
GraphMenu.Size = new Size(1449, 42);
|
||||
@ -125,6 +127,20 @@
|
||||
MenuEquationsIntegral.Size = new Size(360, 44);
|
||||
MenuEquationsIntegral.Text = "Compute Integral";
|
||||
//
|
||||
// MenuMisc
|
||||
//
|
||||
MenuMisc.DropDownItems.AddRange(new ToolStripItem[] { MenuMiscCaches });
|
||||
MenuMisc.Name = "MenuMisc";
|
||||
MenuMisc.Size = new Size(83, 38);
|
||||
MenuMisc.Text = "Misc";
|
||||
//
|
||||
// MenuMiscCaches
|
||||
//
|
||||
MenuMiscCaches.Name = "MenuMiscCaches";
|
||||
MenuMiscCaches.Size = new Size(359, 44);
|
||||
MenuMiscCaches.Text = "View Caches";
|
||||
MenuMiscCaches.Click += MenuMiscCaches_Click;
|
||||
//
|
||||
// GraphForm
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(13F, 32F);
|
||||
@ -154,5 +170,7 @@
|
||||
private ToolStripMenuItem MenuEquations;
|
||||
private ToolStripMenuItem MenuEquationsDerivative;
|
||||
private ToolStripMenuItem MenuEquationsIntegral;
|
||||
private ToolStripMenuItem MenuMisc;
|
||||
private ToolStripMenuItem MenuMiscCaches;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,6 @@
|
||||
using Graphing.Graphables;
|
||||
using Graphing.Extensions;
|
||||
using Graphing.Graphables;
|
||||
using System.Text;
|
||||
|
||||
namespace Graphing.Forms;
|
||||
|
||||
@ -346,7 +348,7 @@ public partial class GraphForm : Form
|
||||
static double Integrate(EquationDelegate e, double lower, double upper)
|
||||
{
|
||||
// TODO: a better rendering method could make this much faster.
|
||||
const double step = 1e-1;
|
||||
const double step = 1e-2;
|
||||
|
||||
double factor = 1;
|
||||
if (upper < lower)
|
||||
@ -364,4 +366,33 @@ public partial class GraphForm : Form
|
||||
return sum * factor;
|
||||
}
|
||||
}
|
||||
|
||||
private void MenuMiscCaches_Click(object? sender, EventArgs e)
|
||||
{
|
||||
// TODO: Replace with a form with a pie chart of the use by equation
|
||||
// and the ability to reset them.
|
||||
StringBuilder message = new();
|
||||
long total = 0;
|
||||
foreach (Graphable able in ables)
|
||||
{
|
||||
if (able is Equation equ)
|
||||
{
|
||||
long size = equ.GetCacheBytes();
|
||||
message.AppendLine($"{able.Name}: {size.FormatAsBytes()}");
|
||||
|
||||
total += size;
|
||||
}
|
||||
}
|
||||
|
||||
message.AppendLine($"\nTotal: {total.FormatAsBytes()}\n\nClick \"No\" to erase caches.");
|
||||
|
||||
DialogResult result = MessageBox.Show(message.ToString(), "Graph Caches", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
|
||||
if (result == DialogResult.No)
|
||||
{
|
||||
foreach (Graphable able in ables)
|
||||
{
|
||||
if (able is Equation equ) equ.EraseCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,23 +8,33 @@ public class Equation : Graphable
|
||||
|
||||
private readonly EquationDelegate equ;
|
||||
|
||||
private readonly List<Float2> cache;
|
||||
|
||||
public Equation(EquationDelegate equ)
|
||||
{
|
||||
equationNum++;
|
||||
Name = $"Equation {equationNum}";
|
||||
|
||||
this.equ = equ;
|
||||
cache = [];
|
||||
}
|
||||
|
||||
public override IEnumerable<Line2d> GetItemsToRender(in GraphForm graph)
|
||||
{
|
||||
const int step = 10;
|
||||
double epsilon = Math.Abs(graph.ScreenSpaceToGraphSpace(new Int2(0, 0)).x
|
||||
- graph.ScreenSpaceToGraphSpace(new Int2(step / 2, 0)).x) / 5;
|
||||
|
||||
List<Line2d> lines = [];
|
||||
|
||||
bool addedToDictionary = false;
|
||||
double previousX = graph.MinVisibleGraph.x;
|
||||
double previousY = equ(previousX);
|
||||
for (int i = 1; i < graph.ClientRectangle.Width; i += 10)
|
||||
double previousY = GetFromCache(previousX, epsilon, ref addedToDictionary);
|
||||
|
||||
for (int i = 1; i < graph.ClientRectangle.Width; i += step)
|
||||
{
|
||||
double currentX = graph.ScreenSpaceToGraphSpace(new Int2(i, 0)).x;
|
||||
double currentY = equ(currentX);
|
||||
double currentY = GetFromCache(currentX, epsilon, ref addedToDictionary);
|
||||
if (Math.Abs(currentY - previousY) <= 10)
|
||||
{
|
||||
lines.Add(new Line2d(new Float2(previousX, previousY), new Float2(currentX, currentY)));
|
||||
@ -32,10 +42,50 @@ public class Equation : Graphable
|
||||
previousX = currentX;
|
||||
previousY = currentY;
|
||||
}
|
||||
|
||||
if (addedToDictionary) cache.Sort((a, b) => a.y.CompareTo(b.y));
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
public EquationDelegate GetDelegate() => equ;
|
||||
|
||||
public void EraseCache() => cache.Clear();
|
||||
private double GetFromCache(double x, double epsilon, ref bool addedToDictionary)
|
||||
{
|
||||
(double dist, double nearest) = NearestCachedPoint(x);
|
||||
if (dist < epsilon) return nearest;
|
||||
else
|
||||
{
|
||||
addedToDictionary = true;
|
||||
double result = equ(x);
|
||||
cache.Add(new(x, result));
|
||||
// TODO: Rather than sorting the whole list when we add a single number,
|
||||
// we could just insert it.
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private (double dist, double y) NearestCachedPoint(double x)
|
||||
{
|
||||
// TODO: Replace with a binary search system.
|
||||
double closestDist = double.PositiveInfinity;
|
||||
double closest = 0;
|
||||
|
||||
foreach (Float2 p in cache)
|
||||
{
|
||||
double dist = Math.Abs(x - p.x);
|
||||
if (dist < closestDist)
|
||||
{
|
||||
closestDist = dist;
|
||||
closest = p.y;
|
||||
}
|
||||
}
|
||||
|
||||
return (closestDist, closest);
|
||||
}
|
||||
|
||||
public long GetCacheBytes() => cache.Count * 16;
|
||||
}
|
||||
|
||||
public delegate double EquationDelegate(double x);
|
||||
|
||||
@ -13,7 +13,8 @@ internal static class Program
|
||||
Application.SetHighDpiMode(HighDpiMode.PerMonitorV2);
|
||||
|
||||
GraphForm graph = new("One Of The Graphing Calculators Of All Time");
|
||||
graph.Graph(new Equation(Math.Cos));
|
||||
graph.Graph(new Equation(x => Math.Pow(2, x)));
|
||||
graph.Graph(new Equation(Math.Log2));
|
||||
|
||||
Application.Run(graph);
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
@ -9,6 +8,14 @@
|
||||
<RootNamespace>Graphing.Testing</RootNamespace>
|
||||
<AssemblyName>ThatOneNerd.Graphing.Testing</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<OutputType>WinExe</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Base\Base.csproj" />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user