Created
July 18, 2020 14:30
-
-
Save zdimension/91f7c754a54d345f124d6e1bb62cdada to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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