Skip to content

Instantly share code, notes, and snippets.

@zdimension
Created July 18, 2020 14:30
Show Gist options
  • Save zdimension/91f7c754a54d345f124d6e1bb62cdada to your computer and use it in GitHub Desktop.
Save zdimension/91f7c754a54d345f124d6e1bb62cdada to your computer and use it in GitHub Desktop.
public class Unit
{
public string Name { get; }
public Lazy<Unit> _derivative;
public Unit Derivative => _derivative.Value;
private Lazy<Unit> _antiderivative;
public Unit Integral => _antiderivative.Value;
private static readonly Dictionary<string, Unit> _units = new Dictionary<string, Unit>();
public override string ToString()
{
return Name;
}
private Unit(string name, Lazy<Unit> deriv, Lazy<Unit> integ)
{
Name = name;
_derivative = deriv;
_antiderivative = integ;
}
private static readonly (string, string)[] Powers =
{
("⋅s³", "⋅s²"),
("⋅s²", "⋅s"),
( "/s", "/s²" ),
( "/s²", "/s³" ),
};
public static string IncreasePower(string suffix)
{
if (suffix.EndsWith("/s"))
return suffix[..^2];
foreach (var (bef, aft) in Powers)
{
if (suffix.EndsWith(aft, StringComparison.InvariantCulture))
return suffix[..^aft.Length] + bef;
}
return suffix + "⋅s";
}
public static string DecreasePower(string suffix)
{
if (suffix.EndsWith("⋅s"))
return suffix[..^2];
foreach (var (bef, aft) in Powers)
{
if (suffix.EndsWith(bef, StringComparison.InvariantCulture))
return suffix[..^bef.Length] + aft;
}
return suffix + "/s";
}
public static Unit Create(string name, Unit? deriv = null, Unit? integ = null)
{
Unit res;
var lDeriv = new Lazy<Unit>(() => deriv ?? Create(DecreasePower(name)));
var lInteg = new Lazy<Unit>(() => integ ?? Create(IncreasePower(name)));
if (!_units.TryGetValue(name, out res!))
{
res = _units[name] = new Unit(name,
lDeriv,
lInteg);
}
var lRes = new Lazy<Unit>(() => res);
if (deriv != null)
deriv._antiderivative = lRes;
if (integ != null)
integ._derivative = lRes;
return res;
}
public static implicit operator Unit(string name)
{
return Create(name);
}
public static readonly Unit Length = Create("m");
public static readonly Unit Velocity = Length.Derivative;
public static readonly Unit Acceleration = Velocity.Derivative;
public static readonly Unit Mass = Create("kg");
public static readonly Unit Density = Create("kg/m²");
public static readonly Unit MomentOfInertia = Create("kg⋅m²");
public static readonly Unit Power = Create("W");
public static readonly Unit Force = Create("N");
public static readonly Unit Torque = Create("N⋅m", Power, "J⋅s");
public static readonly Unit Momentum = Force.Integral;
public static readonly Unit AngularMomentum = Torque.Integral;
public static readonly Unit Angle = Create("rad");
public static readonly Unit AngularVelocity = Angle.Derivative;
public static readonly Unit AngularAcceleration = AngularVelocity.Derivative;
public static readonly Unit Energy = Create("J", Power);
public static readonly Unit AttractionLinear = Create("Nm/kg²");
public static readonly Unit AttractionQuadratic = Create("Nm²/kg²");
public Unit Differentiate(int degree = 1)
{
var unit = this;
for (var i = 0; i < degree; i++)
unit = unit.Derivative;
return unit;
}
public Unit Integrate(int degree = 1)
{
var unit = this;
for (var i = 0; i < degree; i++)
unit = unit.Integral;
return unit;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment