From dd0e1710fe7e1573127ecc7a210149a47f4c0257 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 26 Oct 2026 10:31:09 +0000 Subject: [PATCH 1/8] [patch] Resolve dot segments in IsRoot, DirectoryPath.Parent and Depth; skip unrepresentable entries in GetContents IsRoot is now true exactly when Parent returns the path itself, so walking upwards from /home/.. stops (#479). DirectoryPath.Parent resolves rooted paths and normalizes relative ones as the typed paths do (#478). Depth counts directories below the root of the resolved path, or levels below the first segment of the normalized relative path, instead of separator characters (#466). GetContents skips an entry whose path fails validation rather than throwing for the whole listing (#445). Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01RjhaUGAEJWfvbkaV4MjYkY --- .../Implementations/AbsoluteDirectoryPath.cs | 42 ++-- .../Implementations/RelativeDirectoryPath.cs | 29 ++- Semantics.Paths/Primitives/DirectoryPath.cs | 21 +- Semantics.Paths/SemanticDirectoryPath.cs | 44 +++- .../Utilities/SpanPathUtilities.cs | 23 +++ Semantics.Test/Paths/DotSegmentPathTests.cs | 192 ++++++++++++++++++ 6 files changed, 307 insertions(+), 44 deletions(-) create mode 100644 Semantics.Test/Paths/DotSegmentPathTests.cs diff --git a/Semantics.Paths/Implementations/AbsoluteDirectoryPath.cs b/Semantics.Paths/Implementations/AbsoluteDirectoryPath.cs index f71405cc..025c185d 100644 --- a/Semantics.Paths/Implementations/AbsoluteDirectoryPath.cs +++ b/Semantics.Paths/Implementations/AbsoluteDirectoryPath.cs @@ -72,20 +72,33 @@ public AbsoluteDirectoryPath Parent /// Gets the name of this directory (the last component of the path). /// /// A representing just the directory name. + /// + /// This is the last component as written, not as resolved: the name of /home/user/.. is ... + /// Resolve the path first, for example through of a child, when the directory's own + /// name is wanted. + /// public FileName Name => _cachedName ??= FileName.Create(Path.GetFileName(WeakString) ?? ""); // Cache for depth calculation private int? _cachedDepth; /// - /// Gets the depth of this directory path (number of directory separators). - /// For example, "a/b/c" has depth 2, "a" has depth 0. + /// Gets the depth of this directory below its root: the number of directories between the root and this one, + /// counting this one. /// - /// The number of directory separators in the path. + /// + /// 0 for a root such as / or C:\, 1 for /home, 2 for /home/user. . and + /// .. segments are resolved first, so /home/user/.. has depth 1, and a trailing separator + /// does not add a level. + /// + /// + /// The depth always agrees with : a path that is not a root is exactly one level deeper + /// than its parent. + /// public int Depth => _cachedDepth ??= CalculateDepth(WeakString); /// - /// Calculates directory depth using span semantics for optimal performance. + /// Counts the segments after the root of the resolved path. /// /// The path to analyze. /// The directory depth. @@ -96,16 +109,9 @@ private static int CalculateDepth(string path) return 0; } - ReadOnlySpan span = path.AsSpan(); - int depth = 0; - for (int i = 0; i < span.Length; i++) - { - if (span[i] == Path.DirectorySeparatorChar || span[i] == Path.AltDirectorySeparatorChar) - { - depth++; - } - } - return depth; + string full = Path.GetFullPath(path); + string root = Path.GetPathRoot(full) ?? string.Empty; + return SpanPathUtilities.CountSegments(full.AsSpan(root.Length)); } // Cache for root check @@ -114,8 +120,12 @@ private static int CalculateDepth(string path) /// /// Determines whether this directory is a root directory. /// - /// true if this is a root directory; otherwise, false. - public bool IsRoot => _cachedIsRoot ??= Path.GetPathRoot(WeakString) == WeakString; + /// + /// if this path resolves to a root, which is exactly when returns + /// this same path; otherwise, . . and .. segments are resolved first, so + /// /home/.. is a root. + /// + public bool IsRoot => _cachedIsRoot ??= ReferenceEquals(Parent, this); /// /// Creates an absolute file path for files in this directory. diff --git a/Semantics.Paths/Implementations/RelativeDirectoryPath.cs b/Semantics.Paths/Implementations/RelativeDirectoryPath.cs index 4809e980..2dc3337e 100644 --- a/Semantics.Paths/Implementations/RelativeDirectoryPath.cs +++ b/Semantics.Paths/Implementations/RelativeDirectoryPath.cs @@ -78,33 +78,28 @@ private RelativeDirectoryPath ComputeParent() private int? _cachedDepth; /// - /// Gets the depth of this relative directory path (number of directory levels). + /// Gets the depth of this relative directory path: the number of levels below its first segment. /// - /// The depth of the directory path. - public int Depth => _cachedDepth ??= CalculateDepth(WeakString); + /// + /// 0 for a, 1 for a/b, 2 for a/b/c. The path is normalized first, the same way as + /// , so ./a has the same depth as a, a trailing separator does not add a + /// level, and a/.., . and the empty path, which all name the starting directory, have depth 0. + /// + public int Depth => _cachedDepth ??= CalculateDepth(); /// - /// Calculates directory depth using span semantics for optimal performance. + /// Counts the segments of the normalized path, less the first. /// - /// The path to analyze. /// The directory depth. - private static int CalculateDepth(string path) + private int CalculateDepth() { - if (string.IsNullOrEmpty(path)) + string normalized = Normalize().WeakString; + if (normalized.Length == 0 || normalized == ".") { return 0; } - ReadOnlySpan span = path.AsSpan(); - int depth = 0; - for (int i = 0; i < span.Length; i++) - { - if (span[i] == Path.DirectorySeparatorChar || span[i] == Path.AltDirectorySeparatorChar) - { - depth++; - } - } - return depth; + return SpanPathUtilities.CountSegments(normalized.AsSpan()) - 1; } /// diff --git a/Semantics.Paths/Primitives/DirectoryPath.cs b/Semantics.Paths/Primitives/DirectoryPath.cs index 6ec43c43..9c325bed 100644 --- a/Semantics.Paths/Primitives/DirectoryPath.cs +++ b/Semantics.Paths/Primitives/DirectoryPath.cs @@ -12,13 +12,28 @@ public sealed record DirectoryPath : SemanticDirectoryPath, IDire /// /// Gets the parent directory of this directory path. /// - /// A representing the parent directory, or an empty path if this is a root directory. + /// + /// A naming the directory that contains this one, or an empty path when this path + /// resolves to a root directory. + /// + /// + /// . and .. segments are resolved before the last segment is dropped, so the parent of + /// /home/user/.. is / rather than /home/user. A rooted path is resolved as + /// resolves it, and a relative one is normalized lexically as + /// normalizes it, so it is never resolved against the working + /// directory: the parent of a/.. is .., and the parent of .. is ../... + /// public DirectoryPath Parent { get { - string? parentPath = Path.GetDirectoryName(WeakString); - return Create(parentPath ?? ""); + if (Path.IsPathRooted(WeakString)) + { + string? parent = Path.GetDirectoryName(Path.GetFullPath(WeakString)); + return Create(parent ?? ""); + } + + return Create(RelativeDirectoryPath.Create(WeakString).Parent.WeakString); } } diff --git a/Semantics.Paths/SemanticDirectoryPath.cs b/Semantics.Paths/SemanticDirectoryPath.cs index c5b9c8d3..3e0bca72 100644 --- a/Semantics.Paths/SemanticDirectoryPath.cs +++ b/Semantics.Paths/SemanticDirectoryPath.cs @@ -17,12 +17,17 @@ public abstract record SemanticDirectoryPath : SemanticPath /// Returns an empty collection if the directory doesn't exist or cannot be accessed. /// /// + /// An entry whose path this library cannot represent, for example one that fails path validation because its + /// name holds a character such as | or its full path is too long, is skipped rather than failing the + /// whole listing, so every entry that can be represented is still returned. + /// /// The returned types depend on the current directory type: /// /// returns and objects /// returns and objects /// returns and objects /// + /// /// public virtual IEnumerable GetContents() { @@ -41,15 +46,10 @@ public virtual IEnumerable GetContents() foreach (string entry in entries) { - if (File.Exists(entry)) + IPath? item = TryCreateEntry(entry); + if (item is not null) { - // It's a file - create appropriate file path type - contents.Add(CreateFilePath(entry)); - } - else if (Directory.Exists(entry)) - { - // It's a directory - create appropriate directory path type - contents.Add(CreateDirectoryPath(entry)); + contents.Add(item); } } @@ -67,6 +67,34 @@ public virtual IEnumerable GetContents() } } + /// + /// Wraps one directory entry as the appropriate path type, or returns when the entry is + /// neither a file nor a directory any more, or its path fails validation. + /// + /// The entry's path, as listed. + /// The wrapped entry, or to skip it. + private IPath? TryCreateEntry(string entry) + { + try + { + if (File.Exists(entry)) + { + return CreateFilePath(entry); + } + + if (Directory.Exists(entry)) + { + return CreateDirectoryPath(entry); + } + } + catch (ArgumentException) + { + // The entry's path fails validation, which says nothing about its siblings. + } + + return null; + } + /// /// Creates an appropriate file path type based on the current directory path type. /// diff --git a/Semantics.Paths/Utilities/SpanPathUtilities.cs b/Semantics.Paths/Utilities/SpanPathUtilities.cs index da8413ad..8648d536 100644 --- a/Semantics.Paths/Utilities/SpanPathUtilities.cs +++ b/Semantics.Paths/Utilities/SpanPathUtilities.cs @@ -150,4 +150,27 @@ public static bool EndsWithDirectorySeparator(string path) (path[path.Length - 1] == Path.DirectorySeparatorChar || path[path.Length - 1] == Path.AltDirectorySeparatorChar); #endif } + + /// + /// Counts the non-empty segments of a path, so repeated, leading and trailing separators add nothing. + /// + /// The path span to count, without its root. + /// The number of segments. + public static int CountSegments(ReadOnlySpan path) + { + int count = 0; + bool inSegment = false; + foreach (char c in path) + { + bool isSeparator = c == Path.DirectorySeparatorChar || c == Path.AltDirectorySeparatorChar; + if (!isSeparator && !inSegment) + { + count++; + } + + inSegment = !isSeparator; + } + + return count; + } } diff --git a/Semantics.Test/Paths/DotSegmentPathTests.cs b/Semantics.Test/Paths/DotSegmentPathTests.cs new file mode 100644 index 00000000..9bcf78fb --- /dev/null +++ b/Semantics.Test/Paths/DotSegmentPathTests.cs @@ -0,0 +1,192 @@ +// Copyright (c) 2023-2026 ktsu-dev contributors + +namespace ktsu.Semantics.Test.Paths; + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using ktsu.Semantics.Paths; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +/// +/// Tests that . and .. segments are resolved by , +/// and both Depth properties, and that a directory listing survives an +/// entry the library cannot represent. +/// +[TestClass] +public class DotSegmentPathTests +{ + private static AbsoluteDirectoryPath Absolute(string path) => AbsoluteDirectoryPath.Create(path); + + private static RelativeDirectoryPath Relative(string path) => RelativeDirectoryPath.Create(path); + + private static DirectoryPath Polymorphic(string path) => DirectoryPath.Create(path); + + private static readonly string[] ValidEntries = ["ok.txt", "sub"]; + + private static readonly string Sep = Path.DirectorySeparatorChar.ToString(); + + /// Issue #479: a path that resolves to a root is a root. + [TestMethod] + public void IsRoot_IsTrueExactlyWhenParentIsThePathItself() + { + string[] paths = + [ + TestPaths.Root, + TestPaths.Absolute("home", ".."), + TestPaths.Absolute("home", "user", "..", ".."), + TestPaths.Absolute("home"), + TestPaths.Absolute("home", "user", ".."), + ]; + + foreach (string path in paths) + { + AbsoluteDirectoryPath dir = Absolute(path); + Assert.AreEqual(ReferenceEquals(dir.Parent, dir), dir.IsRoot, path); + } + + Assert.IsTrue(Absolute(TestPaths.Absolute("home", "..")).IsRoot); + Assert.IsFalse(Absolute(TestPaths.Absolute("home", "user", "..")).IsRoot); + } + + /// Issue #479: the documented upward walk stops at the root from a dotted path. + [TestMethod] + public void WalkingUpwards_FromADottedPath_StopsAtTheRoot() + { + foreach (string start in new[] { TestPaths.Absolute("home", ".."), TestPaths.Absolute("a", "b", "..", "c", ".") }) + { + AbsoluteDirectoryPath dir = Absolute(start); + int steps = 0; + while (!dir.IsRoot) + { + dir = dir.Parent; + Assert.IsLessThan(10, ++steps, $"Walking up from '{start}' did not stop."); + } + + Assert.AreEqual(TestPaths.Root, Path.GetFullPath(dir.WeakString)); + } + } + + /// Issue #478: the polymorphic primitive resolves dot segments like the typed paths do. + [TestMethod] + public void DirectoryPathParent_ResolvesDotSegments() + { + Assert.AreEqual(TestPaths.Root, Polymorphic(TestPaths.Absolute("home", "user", "..")).Parent.WeakString); + Assert.AreEqual(TestPaths.Absolute("home"), Polymorphic(TestPaths.Absolute("home", "user", ".")).Parent.WeakString); + Assert.AreEqual("..", Polymorphic("a" + Sep + "..").Parent.WeakString); + Assert.AreEqual(".." + Sep + "..", Polymorphic("..").Parent.WeakString); + Assert.AreEqual("a", Polymorphic("a" + Sep + "." + Sep + "b").Parent.WeakString); + } + + [TestMethod] + public void DirectoryPathParent_OfARoot_IsEmpty() + { + Assert.AreEqual("", Polymorphic(TestPaths.Root).Parent.WeakString); + Assert.AreEqual("", Polymorphic(TestPaths.Absolute("home", "..")).Parent.WeakString); + } + + /// Issue #466: depth counts directories below the root, not separator characters. + [TestMethod] + public void AbsoluteDepth_CountsDirectoriesBelowTheRoot() + { + Assert.AreEqual(0, Absolute(TestPaths.Root).Depth); + Assert.AreEqual(1, Absolute(TestPaths.Absolute("home")).Depth); + Assert.AreEqual(1, Absolute(TestPaths.Absolute("home") + Sep).Depth); + Assert.AreEqual(2, Absolute(TestPaths.Absolute("home", "user")).Depth); + Assert.AreEqual(1, Absolute(TestPaths.Absolute("home", "user", "..")).Depth); + Assert.AreEqual(0, Absolute(TestPaths.Absolute("home", "..")).Depth); + } + + [TestMethod] + public void AbsoluteDepth_IsOneMoreThanTheParents() + { + AbsoluteDirectoryPath dir = Absolute(TestPaths.Absolute("a", "b", "c")); + while (!dir.IsRoot) + { + Assert.AreEqual(dir.Parent.Depth + 1, dir.Depth, dir.WeakString); + dir = dir.Parent; + } + } + + [TestMethod] + [OSCondition(OperatingSystems.Windows)] + [TestCategory("OS-Specific")] + public void AbsoluteDepth_OnWindowsRoots() + { + Assert.AreEqual(0, Absolute(@"C:\").Depth); + Assert.AreEqual(1, Absolute(@"C:\Users").Depth); + } + + [TestMethod] + public void RelativeDepth_IsTakenFromTheNormalizedPath() + { + Assert.AreEqual(0, Relative("a").Depth); + Assert.AreEqual(1, Relative("a" + Sep + "b").Depth); + Assert.AreEqual(0, Relative("." + Sep + "a").Depth); + Assert.AreEqual(0, Relative("a" + Sep).Depth); + Assert.AreEqual(0, Relative("a" + Sep + "..").Depth); + Assert.AreEqual(0, Relative(".").Depth); + Assert.AreEqual(1, Relative("a" + Sep + "." + Sep + "b").Depth); + } + + /// + /// A directory type whose entries fail validation by name, standing in for the names and lengths only some + /// platforms reject, so the listing contract is tested on every platform. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1812:Avoid uninstantiated internal classes", Justification = "Created through SemanticString.Create")] + private sealed record PickyDirectoryPath : SemanticDirectoryPath + { + protected override IFilePath CreateFilePath(string filePath) => + Path.GetFileName(filePath) == "bad.txt" + ? throw new ArgumentException("Rejected for the test.", nameof(filePath)) + : base.CreateFilePath(filePath); + } + + /// Issue #445: one entry that fails validation does not hide the rest. + [TestMethod] + public void GetContents_SkipsAnEntryThatFailsValidation() + { + string root = Path.Combine(Path.GetTempPath(), "semantics-contents-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(root); + try + { + File.WriteAllText(Path.Combine(root, "ok.txt"), "ok"); + Directory.CreateDirectory(Path.Combine(root, "sub")); + File.WriteAllText(Path.Combine(root, "bad.txt"), "rejected"); + + PickyDirectoryPath dir = PickyDirectoryPath.Create(root); + List names = [.. dir.GetContents().Select(p => Path.GetFileName(p.ToString()) ?? "")]; + + CollectionAssert.AreEquivalent(ValidEntries, names); + } + finally + { + Directory.Delete(root, recursive: true); + } + } + + /// Issue #445, with the real Windows length limit rather than a stand-in. + [TestMethod] + [OSCondition(OperatingSystems.Windows)] + [TestCategory("OS-Specific")] + public void GetContents_SkipsAnEntryPastTheWindowsLengthLimit() + { + string root = Path.Combine(Path.GetTempPath(), "semantics-contents-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(root); + try + { + File.WriteAllText(Path.Combine(root, "ok.txt"), "ok"); + Directory.CreateDirectory(Path.Combine(root, "sub")); + File.WriteAllText(Path.Combine(root, new string('x', 250) + ".txt"), "too long"); + + List names = [.. Absolute(root).GetContents().Select(p => Path.GetFileName(p.ToString()) ?? "")]; + + CollectionAssert.AreEquivalent(ValidEntries, names); + } + finally + { + Directory.Delete(root, recursive: true); + } + } +} From 6d28e5c9b129812549532f182a391690146c093b Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 26 Oct 2026 10:34:50 +0000 Subject: [PATCH 2/8] [minor] Color: CSS named colors, alpha-aware contrast, gamut-mapped Oklab mixes NamedColors.Green is CSS's #008000 and the new Lime is #00FF00 (#449). CompositeOver blends source-over in gamma sRGB; ContrastRatio, AccessibilityLevelAgainst and AdjustForContrast measure a translucent color as it looks over the background (#393). AdjustForContrast gamut-maps its lightness candidates by reducing chroma instead of clipping, and falls back to mixing towards black or white, so it reaches the target whenever black or white does (#351). MixOklab and Gradient return in-gamut colors, and Hsl/Hsv.FromSrgb clamp their input and treat a rounding-error spread as gray (#355). Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01RjhaUGAEJWfvbkaV4MjYkY --- Semantics.Color/Color.Conversions.cs | 10 + Semantics.Color/Color.Operations.cs | 186 +++++++++++++--- Semantics.Color/Hsl.cs | 14 +- Semantics.Color/Hsv.cs | 7 +- Semantics.Color/NamedColors.cs | 14 +- Semantics.Color/README.md | 11 +- Semantics.Color/Srgb.cs | 4 + .../Colors/ColorGamutAndAlphaTests.cs | 207 ++++++++++++++++++ 8 files changed, 409 insertions(+), 44 deletions(-) create mode 100644 Semantics.Test/Colors/ColorGamutAndAlphaTests.cs diff --git a/Semantics.Color/Color.Conversions.cs b/Semantics.Color/Color.Conversions.cs index 2bce5413..50077e96 100644 --- a/Semantics.Color/Color.Conversions.cs +++ b/Semantics.Color/Color.Conversions.cs @@ -120,6 +120,11 @@ private static bool IsHexDigit(char c) => /// The Oklab color. /// Straight alpha (default 1.0). /// The linear-RGB color. + /// + /// The conversion is exact and does not gamut-map, so an Oklab value outside sRGB, or a round trip that lands + /// a rounding error past white, gives channels outside 0..1. Call on the result when an + /// in-gamut color is needed; and already return one. + /// public static Color FromOklab(Oklab oklab, double a = 1.0) => oklab.ToColor(a); /// Converts this linear color to . @@ -130,6 +135,11 @@ private static bool IsHexDigit(char c) => /// The Oklch color. /// Straight alpha (default 1.0). /// The linear-RGB color. + /// + /// The conversion is exact and does not gamut-map, so an Oklab value outside sRGB, or a round trip that lands + /// a rounding error past white, gives channels outside 0..1. Call on the result when an + /// in-gamut color is needed; and already return one. + /// public static Color FromOklch(Oklch oklch, double a = 1.0) => oklch.ToOklab().ToColor(a); /// Converts this linear color to (via sRGB). diff --git a/Semantics.Color/Color.Operations.cs b/Semantics.Color/Color.Operations.cs index 28041e17..95b3cafe 100644 --- a/Semantics.Color/Color.Operations.cs +++ b/Semantics.Color/Color.Operations.cs @@ -10,22 +10,65 @@ public readonly partial record struct Color /// Gets the WCAG relative luminance of this color (computed on the linear channels). public double RelativeLuminance => (0.2126 * R) + (0.7152 * G) + (0.0722 * B); - /// Computes the WCAG contrast ratio (1..21) between this color and another. - /// The other color. + /// + /// Composites this color over a background with the source-over operator, the way CSS and every browser + /// blend a translucent color onto what is beneath it. + /// + /// The color underneath. + /// + /// The blended color, with alpha a + b·(1 − a) for this color's alpha a and the background's + /// b. An opaque background gives an opaque result. + /// + /// + /// The blend is computed on the gamma-encoded sRGB channels rather than the linear ones, because that is + /// what browsers do and what WCAG contrast checkers such as axe and Chrome DevTools measure, so a contrast + /// ratio taken from the result agrees with theirs. Blending in linear light would be physically closer to + /// mixing light, and would disagree with every tool a reader checks the ratio against. + /// + public Color CompositeOver(Color background) + { + double a = Clamp01(A); + double b = Clamp01(background.A) * (1.0 - a); + double alpha = a + b; + if (alpha <= 0.0) + { + return new Color(0.0, 0.0, 0.0, 0.0); + } + + Srgb fg = ToSrgb(); + Srgb bg = background.ToSrgb(); + Srgb blended = new( + ((fg.R * a) + (bg.R * b)) / alpha, + ((fg.G * a) + (bg.G * b)) / alpha, + ((fg.B * a) + (bg.B * b)) / alpha); + return FromSrgb(blended, alpha); + } + + /// Computes the WCAG contrast ratio (1..21) between this color and a background. + /// The background color. Its own alpha is ignored: it is treated as opaque. /// The contrast ratio, from 1 (identical luminance) to 21 (black vs white). + /// + /// A translucent color is first composited over the background with , as WCAG + /// checkers do, so the ratio measures what is actually seen: fully transparent text rates 1:1 against + /// anything. For two opaque colors the ratio is symmetric; when this color is translucent it is not, and + /// is the one underneath. + /// public double ContrastRatio(Color other) { - double l1 = RelativeLuminance; - double l2 = other.RelativeLuminance; + Color background = other.WithAlpha(1.0); + Color seen = A >= 1.0 ? this : CompositeOver(background); + double l1 = seen.RelativeLuminance; + double l2 = background.RelativeLuminance; double lighter = Math.Max(l1, l2); double darker = Math.Min(l1, l2); return (lighter + 0.05) / (darker + 0.05); } /// Rates the contrast of this color against a background per WCAG. - /// The background color. + /// The background color, treated as opaque. /// True for large text (lower thresholds). /// The highest the pair satisfies. + /// A translucent color is rated as it looks over the background; see . public AccessibilityLevel AccessibilityLevelAgainst(Color background, bool largeText = false) { double contrast = ContrastRatio(background); @@ -41,14 +84,23 @@ public AccessibilityLevel AccessibilityLevelAgainst(Color background, bool large } /// - /// Adjusts this color's Oklab lightness (preserving hue and chroma) until it meets the requested - /// contrast level against a background. Returns this color unchanged if already sufficient or if - /// no adjustment can reach the target. + /// Adjusts this color until it meets the requested contrast level against a background, changing it as + /// little as it can. /// - /// The background color. + /// The background color, treated as opaque. /// The desired conformance level. /// True for large text (lower thresholds). - /// An adjusted color, clamped to gamut. + /// An adjusted color inside the sRGB gamut, with this color's alpha. + /// + /// The search first moves Oklab lightness, keeping hue, and keeping chroma wherever the sRGB gamut allows it: + /// near black and white a saturated color has no in-gamut form at its own chroma, so chroma is reduced there + /// rather than the channels being clipped, which would shift the hue and the luminance. If no lightness + /// reaches the target, the color is mixed towards black or white instead, so whenever black or white meets + /// the level against this background the result does too. Alpha is kept, and the contrast is measured on the + /// color as it looks over the background (see ), so a color too transparent to + /// reach the target even at black or white is returned unchanged; that, and an already sufficient color, + /// are the only cases that return this color as it is. + /// public Color AdjustForContrast(Color background, AccessibilityLevel target, bool largeText = false) { double required = RequiredContrast(target, largeText); @@ -60,34 +112,38 @@ public Color AdjustForContrast(Color background, AccessibilityLevel target, bool Oklab lab = ToOklab(); double alpha = A; + Color self = this; // Try first the direction whose extreme (white or black) gives the higher contrast against // this background. The two are equal near luminance 0.179, not 0.5, so on a mid-tone // background darkening is usually the only way to reach the target. If the preferred - // direction still falls short, fall back to the other one before giving up. - double bgLum = background.RelativeLuminance; + // direction still falls short, fall back to the other one, then to mixing towards black or + // white, before giving up. + double bgLum = background.WithAlpha(1.0).RelativeLuminance; bool preferLighter = (1.05 / (bgLum + 0.05)) >= ((bgLum + 0.05) / 0.05); - return Search(preferLighter) ?? Search(!preferLighter) ?? this; + return Search(preferLighter, LightnessCandidate) + ?? Search(!preferLighter, LightnessCandidate) + ?? Search(preferLighter, MixCandidate) + ?? Search(!preferLighter, MixCandidate) + ?? this; - Color? Search(bool goLighter) + Color? Search(bool goLighter, Func candidateAt) { - double lo = goLighter ? lab.L : 0.0; - double hi = goLighter ? 1.0 : lab.L; + // t runs from 0 (this color) to 1 (the extreme in the chosen direction), and contrast grows + // as t does: binary-search the smallest movement that meets the requirement. + Color extreme = candidateAt(goLighter, 1.0); + if (extreme.ContrastRatio(background) < required) + { + return null; + } - // Contrast increases monotonically as L moves toward the chosen extreme; binary-search - // the smallest movement that meets the requirement. + double lo = 0.0; + double hi = 1.0; for (int i = 0; i < 30; i++) { double mid = (lo + hi) / 2.0; - Color candidate = Candidate(lab, mid); - bool meets = candidate.ContrastRatio(background) >= required; - - // The interval always shrinks toward the end that satisfies the requirement. When - // lightening that is the upper bound if the midpoint already meets it; when darkening - // the roles swap. Both cases reduce to whether the midpoint landed on the goLighter - // side, so the four-way branch collapses to one comparison. - if (meets == goLighter) + if (candidateAt(goLighter, mid).ContrastRatio(background) >= required) { hi = mid; } @@ -97,14 +153,73 @@ public Color AdjustForContrast(Color background, AccessibilityLevel target, bool } } - Color result = Candidate(lab, goLighter ? hi : lo); - return result.ContrastRatio(background) >= required ? result : null; + Color result = candidateAt(goLighter, hi); + return result.ContrastRatio(background) >= required ? result : extreme; } - Color Candidate(Oklab source, double lightness) => - FromOklab(new Oklab(lightness, source.A, source.B), alpha).Clamp(); + Color LightnessCandidate(bool goLighter, double t) + { + double end = goLighter ? 1.0 : 0.0; + return GamutMapped(new Oklab(lab.L + ((end - lab.L) * t), lab.A, lab.B), alpha); + } + + Color MixCandidate(bool goLighter, double t) + { + Color end = goLighter ? new Color(1.0, 1.0, 1.0, alpha) : new Color(0.0, 0.0, 0.0, alpha); + return self.Clamp().Lerp(end, t).WithAlpha(alpha); + } } + /// + /// Converts an Oklab color to the nearest in-gamut linear color of the same lightness and hue, reducing + /// chroma until it fits, as CSS Color 4 gamut-maps. Lightness at or past 0 or 1 gives black or white. + /// + /// The Oklab color. + /// The straight alpha for the result. + /// A color with every channel in 0..1. + internal static Color GamutMapped(Oklab lab, double alpha) + { + const double tolerance = 1e-6; + + if (lab.L >= 1.0) + { + return new Color(1.0, 1.0, 1.0, Clamp01(alpha)); + } + + if (lab.L <= 0.0) + { + return new Color(0.0, 0.0, 0.0, Clamp01(alpha)); + } + + Color direct = lab.ToColor(alpha); + if (IsInGamut(direct, tolerance)) + { + return direct.Clamp(); + } + + double lo = 0.0; + double hi = 1.0; + for (int i = 0; i < 30; i++) + { + double mid = (lo + hi) / 2.0; + if (IsInGamut(new Oklab(lab.L, lab.A * mid, lab.B * mid).ToColor(alpha), tolerance)) + { + lo = mid; + } + else + { + hi = mid; + } + } + + return new Oklab(lab.L, lab.A * lo, lab.B * lo).ToColor(alpha).Clamp(); + } + + private static bool IsInGamut(Color color, double tolerance) => + color.R >= -tolerance && color.R <= 1.0 + tolerance + && color.G >= -tolerance && color.G <= 1.0 + tolerance + && color.B >= -tolerance && color.B <= 1.0 + tolerance; + /// /// The WCAG contrast ratio a foreground/background pair must reach to satisfy /// . @@ -135,7 +250,12 @@ public double DistanceTo(Color other) /// Mixes this color with another in Oklab space (perceptually uniform). /// The other color. /// The interpolation factor, 0 = this, 1 = other. - /// The mixed color. + /// The mixed color, inside the sRGB gamut. + /// + /// A straight line in Oklab between two in-gamut colors can leave the sRGB gamut, as cyan to blue does, so + /// the mix is gamut-mapped by reducing its chroma at the same lightness and hue. Without that, every HSL + /// adjustment made to the result afterwards would start from channels outside 0..1. + /// public Color MixOklab(Color other, double t) { Oklab a = ToOklab(); @@ -145,7 +265,7 @@ public Color MixOklab(Color other, double t) (a.L * inv) + (b.L * t), (a.A * inv) + (b.A * t), (a.B * inv) + (b.B * t)); - return FromOklab(mixed, (A * inv) + (other.A * t)); + return GamutMapped(mixed, (A * inv) + (other.A * t)); } /// Linearly interpolates this color with another in linear-RGB space. @@ -165,7 +285,7 @@ public Color Lerp(Color other, double t) /// Builds a perceptually-uniform (Oklab) gradient from this color to another. /// The end color. /// The number of colors to produce (at least 2). - /// The gradient, inclusive of both endpoints. + /// The gradient, inclusive of both endpoints; every interior stop is inside the sRGB gamut (see ). /// Thrown when is less than 2. public IReadOnlyList Gradient(Color to, int steps) { diff --git a/Semantics.Color/Hsl.cs b/Semantics.Color/Hsl.cs index be1a0053..319d4664 100644 --- a/Semantics.Color/Hsl.cs +++ b/Semantics.Color/Hsl.cs @@ -13,18 +13,30 @@ namespace ktsu.Semantics.Color; /// Lightness, 0..1. public readonly record struct Hsl(double H, double S, double L) { + /// The channel spread below which a color is treated as gray, so rounding noise has no hue. + internal const double AchromaticTolerance = 1e-6; + /// Converts a gamma-encoded color to HSL. /// The sRGB color. /// The HSL equivalent. + /// + /// HSL is only defined inside the sRGB gamut, so each channel is clamped to 0..1 first. Without that an + /// out-of-gamut input, such as a slightly-over-white Oklab round trip, gives a saturation far above 1 that + /// every later HSL adjustment carries into its result. Channels within 1e-6 of each other, far below + /// anything an 8-bit or 16-bit channel can hold, are treated as gray. + /// public static Hsl FromSrgb(Srgb srgb) { + srgb = srgb.Clamp(); double max = Math.Max(srgb.R, Math.Max(srgb.G, srgb.B)); double min = Math.Min(srgb.R, Math.Min(srgb.G, srgb.B)); double l = (max + min) / 2.0; double h = 0.0; double s = 0.0; - if (max > min) + // Channels a rounding error apart are gray: near white or black the saturation formula divides by + // almost nothing, so a difference of 1e-7 would otherwise read as full saturation. + if (max - min > AchromaticTolerance) { double d = max - min; s = l > 0.5 ? d / (2.0 - max - min) : d / (max + min); diff --git a/Semantics.Color/Hsv.cs b/Semantics.Color/Hsv.cs index f6f14b74..ffacc20f 100644 --- a/Semantics.Color/Hsv.cs +++ b/Semantics.Color/Hsv.cs @@ -16,13 +16,16 @@ public readonly record struct Hsv(double H, double S, double V) /// Converts a gamma-encoded color to HSV. /// The sRGB color. /// The HSV equivalent. + /// HSV is only defined inside the sRGB gamut, so each channel is clamped to 0..1 first. public static Hsv FromSrgb(Srgb srgb) { + srgb = srgb.Clamp(); double max = Math.Max(srgb.R, Math.Max(srgb.G, srgb.B)); double min = Math.Min(srgb.R, Math.Min(srgb.G, srgb.B)); double d = max - min; - double h = d > 0.0 ? Hsl.HueDegrees(srgb, max, d) : 0.0; - double s = max > 0.0 ? d / max : 0.0; + bool chromatic = d > Hsl.AchromaticTolerance; + double h = chromatic ? Hsl.HueDegrees(srgb, max, d) : 0.0; + double s = chromatic && max > 0.0 ? d / max : 0.0; return new Hsv(h, s, max); } diff --git a/Semantics.Color/NamedColors.cs b/Semantics.Color/NamedColors.cs index b41537e7..c160ef6d 100644 --- a/Semantics.Color/NamedColors.cs +++ b/Semantics.Color/NamedColors.cs @@ -5,7 +5,11 @@ namespace ktsu.Semantics.Color; using System; using System.Collections.Generic; -/// A small table of common named colors (CSS/X11 subset), as linear . +/// +/// A small table of common CSS named colors, as linear . Every entry has the value CSS Color +/// Module Level 4 gives it, so a name resolves to the same color it does in a browser: green is CSS's +/// #008000, not X11's #00FF00, which CSS calls lime. +/// public static class NamedColors { /// Opaque black (#000000). @@ -17,8 +21,11 @@ public static class NamedColors /// Opaque red (#FF0000). public static Color Red => Color.FromHex("#FF0000"); - /// Opaque green (#00FF00). - public static Color Green => Color.FromHex("#00FF00"); + /// Opaque green (#008000), as CSS defines it. Full-intensity green is . + public static Color Green => Color.FromHex("#008000"); + + /// Opaque lime (#00FF00), full-intensity green. + public static Color Lime => Color.FromHex("#00FF00"); /// Opaque blue (#0000FF). public static Color Blue => Color.FromHex("#0000FF"); @@ -50,6 +57,7 @@ public static class NamedColors ["white"] = White, ["red"] = Red, ["green"] = Green, + ["lime"] = Lime, ["blue"] = Blue, ["yellow"] = Yellow, ["cyan"] = Cyan, diff --git a/Semantics.Color/README.md b/Semantics.Color/README.md index cbb28842..1d10160c 100644 --- a/Semantics.Color/README.md +++ b/Semantics.Color/README.md @@ -23,11 +23,11 @@ On top of that foundation the package adds perceptual operations in the Oklab co - **Linear RGB as the hub**: `Color` stores linear RGBA in 0..1, and all mixing, interpolation, and luminance math happens there. - **Color spaces**: sRGB (`Srgb`), HSL (`Hsl`), HSV (`Hsv`), Oklab (`Oklab`), and Oklch (`Oklch`). Every color type (including `Color`) converts directly to and from every other through `From*` / `To*` methods. Each hop is routed through the nearest shared hub, so a conversion crosses the gamma boundary at most once and never takes a redundant gamma round-trip. - **Interop**: hex parse and format (`#RGB`, `#RRGGBB`, `#RRGGBBAA`), 8-bit byte tuples, and linear or sRGB `Vector3` / `Vector4` output (the sRGB vectors are what ImGui expects). -- **WCAG accessibility**: relative luminance, contrast ratio (1..21), conformance rating against a background, and `AdjustForContrast` which binary-searches Oklab lightness to hit a target while preserving hue and chroma. +- **WCAG accessibility**: relative luminance, contrast ratio (1..21), conformance rating against a background, and `AdjustForContrast` which binary-searches Oklab lightness to hit a target while preserving hue, reducing chroma only where the sRGB gamut requires it and mixing towards black or white when lightness alone cannot reach the target. A translucent foreground is measured as it looks composited over the background, as WCAG checkers do. - **Color vision simulation**: `Simulate(deficiency, severity)` shows a color as someone with protan, deutan, or tritan color vision sees it, from the Machado, Oliveira, and Fernandes (2009) matrices at any severity from 0 to 1. - **Perceptual operations**: Oklab distance (`DistanceTo`), perceptually uniform mixing (`MixOklab`), and Oklab gradients (`Gradient`), alongside plain linear `Lerp`. - **Adjustments**: lighten/darken, saturate/desaturate, hue offset, grayscale, and invert. HSL-based on `Color`, `Hsl`, and `Srgb`; perceptually-uniform (lightness/chroma) variants on `Oklch`. -- **Named colors**: a CSS/X11 subset with case-insensitive lookup. +- **Named colors**: a subset of the CSS named colors, with CSS's values (`green` is `#008000`, `lime` is `#00FF00`) and case-insensitive lookup. ## Installation @@ -181,11 +181,12 @@ The canonical color: linear RGBA, each channel `double` in 0..1. A `readonly rec | Name | Return Type | Description | |------|-------------|-------------| | `RelativeLuminance` | `double` | WCAG luminance. | -| `ContrastRatio(other)` | `double` | WCAG ratio, 1..21. | +| `CompositeOver(background)` | `Color` | Source-over blend in gamma sRGB, as browsers blend. | +| `ContrastRatio(other)` | `double` | WCAG ratio, 1..21, with a translucent color composited over `other` first. | | `AccessibilityLevelAgainst(background, largeText = false)` | `AccessibilityLevel` | Conformance rating. | -| `AdjustForContrast(background, target, largeText = false)` | `Color` | Nudge lightness to meet a target level. | +| `AdjustForContrast(background, target, largeText = false)` | `Color` | Nudge lightness (or mix towards black or white) to meet a target level. | | `DistanceTo(other)` | `double` | Perceptual Oklab distance. | -| `MixOklab(other, t)` | `Color` | Perceptually uniform mix (`t = 0` returns this, `t = 1` returns other). | +| `MixOklab(other, t)` | `Color` | Perceptually uniform mix (`t = 0` returns this, `t = 1` returns other), gamut-mapped into sRGB. | | `Lerp(other, t)` | `Color` | Linear-RGB interpolation. | | `Gradient(to, steps)` | `IReadOnlyList` | Oklab gradient, inclusive of endpoints (`steps >= 2`). | | `Simulate(deficiency, severity)` | `Color` | The color as seen with a color vision deficiency (Machado et al. 2009), severity 0..1. | diff --git a/Semantics.Color/Srgb.cs b/Semantics.Color/Srgb.cs index 542d4a8e..559ebdd5 100644 --- a/Semantics.Color/Srgb.cs +++ b/Semantics.Color/Srgb.cs @@ -78,6 +78,10 @@ public static Srgb FromLinear(Color color) => /// The inverted color. public Srgb Invert() => new(1.0 - R, 1.0 - G, 1.0 - B); + /// Returns a copy with every channel clamped to the 0..1 range. + /// The clamped color. + public Srgb Clamp() => new(Color.Clamp01(R), Color.Clamp01(G), Color.Clamp01(B)); + // Cylindrical adjustments. sRGB has no saturation/lightness/hue axes of its own, so these route // through HSL (a within-family hop, no gamma round-trip) and return sRGB. Same semantics as the // HSL operations of the same name. diff --git a/Semantics.Test/Colors/ColorGamutAndAlphaTests.cs b/Semantics.Test/Colors/ColorGamutAndAlphaTests.cs new file mode 100644 index 00000000..557d0ccb --- /dev/null +++ b/Semantics.Test/Colors/ColorGamutAndAlphaTests.cs @@ -0,0 +1,207 @@ +// Copyright (c) 2023-2026 ktsu-dev contributors + +namespace ktsu.Semantics.Test.Colors; + +using System.Collections.Generic; + +using ktsu.Semantics.Color; + +/// +/// Tests for named colors matching CSS (#449), contrast seeing alpha (#393), contrast adjustment reaching the +/// target for saturated colors (#351), and Oklab results staying in gamut for later HSL work (#355). +/// +[TestClass] +public class ColorGamutAndAlphaTests +{ + private static readonly Color White = NamedColors.White; + + // CSS Color Module Level 4, section 6.1, for every name the table holds. + private static readonly Dictionary CssValues = new() + { + ["black"] = "#000000", + ["white"] = "#FFFFFF", + ["red"] = "#FF0000", + ["green"] = "#008000", + ["lime"] = "#00FF00", + ["blue"] = "#0000FF", + ["yellow"] = "#FFFF00", + ["cyan"] = "#00FFFF", + ["magenta"] = "#FF00FF", + ["gray"] = "#808080", + ["grey"] = "#808080", + ["orange"] = "#FFA500", + ["purple"] = "#800080", + }; + + [TestMethod] + public void NamedColors_MatchCss() + { + foreach (KeyValuePair entry in CssValues) + { + Assert.IsTrue(NamedColors.TryGet(entry.Key, out Color color), entry.Key); + Assert.AreEqual(entry.Value, color.ToHex(), entry.Key); + } + + Assert.AreEqual("#008000", NamedColors.Green.ToHex()); + Assert.AreEqual("#00FF00", NamedColors.Lime.ToHex()); + } + + [TestMethod] + public void NamedColors_EveryOpaqueEntryIsPinned() + { + foreach (string name in NamedColors.All.Keys) + { + Assert.IsTrue(name == "transparent" || CssValues.ContainsKey(name), $"'{name}' has no CSS value in this test."); + } + } + + [TestMethod] + public void ContrastRatio_OfTransparentIsOne() + { + Assert.AreEqual(1.0, NamedColors.Transparent.ContrastRatio(White), 1e-9); + Assert.AreEqual(AccessibilityLevel.Fail, NamedColors.Transparent.AccessibilityLevelAgainst(White)); + } + + [TestMethod] + public void ContrastRatio_OfAFaintColorIsMeasuredAsBlended() + { + Color faint = Color.FromLinear(0, 0, 0, 0.05); + + Assert.AreEqual(AccessibilityLevel.Fail, faint.AccessibilityLevelAgainst(White)); + Assert.IsLessThan(1.2, faint.ContrastRatio(White)); + } + + [TestMethod] + public void ContrastRatio_OfOpaqueColorsIsUnchanged() + { + Assert.AreEqual(21.0, NamedColors.Black.ContrastRatio(White), 1e-9); + Assert.AreEqual(21.0, White.ContrastRatio(NamedColors.Black), 1e-9); + Assert.AreEqual(NamedColors.Gray.ContrastRatio(White), White.ContrastRatio(NamedColors.Gray), 1e-12); + } + + [TestMethod] + public void CompositeOver_BlendsInSrgbLikeABrowser() + { + Color halfBlack = Color.FromLinear(0, 0, 0, 0.5); + Color blended = halfBlack.CompositeOver(White); + + // 50% black over white is sRGB 0.5 in every channel, #808080 rounded as browsers render it. + Assert.AreEqual(0.5, blended.ToSrgb().R, 1e-9); + Assert.AreEqual(1.0, blended.A, 1e-12); + Assert.AreEqual(White, NamedColors.Transparent.CompositeOver(White)); + } + + [TestMethod] + public void AdjustForContrast_FixesATranslucentColorWhenItCan() + { + Color halfGray = Color.FromHex("#888888").WithAlpha(0.6); + Color adjusted = halfGray.AdjustForContrast(White, AccessibilityLevel.AA); + + Assert.AreEqual(0.6, adjusted.A, 1e-12); + Assert.IsGreaterThanOrEqualTo(4.5, adjusted.ContrastRatio(White)); + } + + [TestMethod] + public void AdjustForContrast_ReturnsATooFaintColorUnchanged() + { + Color faint = Color.FromLinear(0, 0, 0, 0.05); + Assert.AreEqual(faint, faint.AdjustForContrast(White, AccessibilityLevel.AAA)); + } + + [TestMethod] + [DataRow("#0000FF", "#777777", AccessibilityLevel.AA)] + [DataRow("#8000FF", "#777777", AccessibilityLevel.AA)] + [DataRow("#0000AA", "#777777", AccessibilityLevel.AA)] + [DataRow("#FF0000", "#0000FF", AccessibilityLevel.AAA)] + [DataRow("#FF00FF", "#0000FF", AccessibilityLevel.AAA)] + public void AdjustForContrast_ReachesTheTargetForSaturatedColors(string foreground, string background, AccessibilityLevel level) + { + Color fg = Color.FromHex(foreground); + Color bg = Color.FromHex(background); + double required = level == AccessibilityLevel.AAA ? 7.0 : 4.5; + + Color adjusted = fg.AdjustForContrast(bg, level); + + Assert.IsGreaterThanOrEqualTo(required, adjusted.ContrastRatio(bg), $"{foreground} on {background} gave {adjusted.ToHex()}"); + AssertInGamut(adjusted); + } + + [TestMethod] + public void AdjustForContrast_KeepsTheHueOfABlueItDarkens() + { + Color adjusted = Color.FromHex("#0000FF").AdjustForContrast(Color.FromHex("#777777"), AccessibilityLevel.AA); + (byte r, byte g, byte b, byte _) = adjusted.ToBytes(); + + Assert.IsGreaterThan(r, b, adjusted.ToHex()); + Assert.IsGreaterThan(g, b, adjusted.ToHex()); + } + + [TestMethod] + public void HslAdjustments_AfterAnOklabRoundTripOfWhite() + { + Color roundTripped = Color.FromOklab(White.ToOklab()); + + Assert.AreEqual(0.0, roundTripped.ToHsl().S, 1e-9); + Assert.AreEqual("#7F7F7F", roundTripped.DarkenBy(0.5).ToHex()); + Assert.AreEqual("#7F7F7F", White.MixOklab(White, 0.5).DarkenBy(0.5).ToHex()); + } + + [TestMethod] + public void LightenBy_OfAnOutOfGamutOklchGreenIsNotBlack() + { + Color lightened = Color.FromOklch(new Oklch(0.7, 0.3, 150)).LightenBy(0.1); + Assert.AreNotEqual("#000000", lightened.ToHex()); + } + + [TestMethod] + public void MixOklabAndGradient_StayInGamut() + { + Color[] primaries = + [ + NamedColors.Black, NamedColors.White, NamedColors.Red, NamedColors.Lime, + NamedColors.Blue, NamedColors.Yellow, NamedColors.Cyan, NamedColors.Magenta, + ]; + + foreach (Color a in primaries) + { + foreach (Color b in primaries) + { + Color mixed = a.MixOklab(b, 0.5); + AssertInGamut(mixed); + Hsl hsl = mixed.ToHsl(); + Assert.IsTrue(hsl.S is >= 0.0 and <= 1.0 && hsl.L is >= 0.0 and <= 1.0, $"{a.ToHex()} + {b.ToHex()} gave {hsl}"); + + foreach (Color stop in a.Gradient(b, 5)) + { + AssertInGamut(stop); + } + } + } + } + + [TestMethod] + public void CyanMixedWithBlue_DesaturatesRatherThanDarkens() + { + Color mixed = NamedColors.Cyan.MixOklab(NamedColors.Blue, 0.5); + Assert.AreNotEqual("#292929", mixed.ToGrayscale().ToHex()); + double saturation = mixed.ToHsl().S; + Assert.AreEqual(System.Math.Max(0.0, saturation - 0.3), mixed.DesaturateBy(0.3).ToHsl().S, 0.02); + } + + [TestMethod] + public void HslAndHsv_OfOutOfGamutInputAreInRange() + { + Srgb over = new(1.0000001, 0.99999998, 0.9999997); + Assert.AreEqual(0.0, Hsl.FromSrgb(over).S, 1e-6); + + Hsv hsv = Hsv.FromSrgb(new Srgb(-0.2, 0.5, 1.3)); + Assert.IsTrue(hsv.S is >= 0.0 and <= 1.0 && hsv.V is >= 0.0 and <= 1.0, hsv.ToString()); + } + + private static void AssertInGamut(Color color) + { + Assert.IsTrue( + color.R is >= 0.0 and <= 1.0 && color.G is >= 0.0 and <= 1.0 && color.B is >= 0.0 and <= 1.0, + $"{color} is out of gamut"); + } +} From 5f727f02d01b35e658f0e72125cb164ad43926bb Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 26 Oct 2026 10:49:36 +0000 Subject: [PATCH 3/8] [patch] Quantities: constants per field, decimal logs, positive guards, division by zero, scaled vector lengths, bounded roots - domains.json: AbsoluteZeroInCelsius is -273.15, WaterIonProduct is 1e-14 and MolarVolumeSTP is in m3/mol; mu0/epsilon0 no longer claim to be exact (#386). - Each physical constant is its own lazily filled field, so one that a storage type cannot hold throws alone, and one that would lose its precision throws instead of reading as zero (#392). - Logarithmic conversions throw ArgumentOutOfRangeException for a level the storage type cannot hold (a linear zero with decimal or integer storage) and OverflowException going back, as documented (#352). - Wavelength, Period and HalfLife keep EnsurePositive through scaling, narrowing and subtraction (#354). - Every generated division throws DivideByZeroException for a zero divisor, including vector / scalar, cross-dimension operators and Normalize() of a zero vector (#480). - Vector Length() and Distance() go through StorageMath.Hypot, scaled by the largest component, so int, decimal and float vectors whose squares overflow still have a length (#327). - Cbrt/RootN stop for PreciseNumber instead of hanging (#457). Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01RjhaUGAEJWfvbkaV4MjYkY --- CLAUDE.md | 36 +++- .../AudioEngineering/Decibels.cs | 10 +- Semantics.Quantities/AudioEngineering/Gain.cs | 3 +- .../Cents.g.cs | 8 +- .../Decibels.g.cs | 16 +- .../DirectionalityIndex.g.cs | 8 +- .../PH.g.cs | 8 +- .../Semitones.g.cs | 8 +- .../SoundIntensityLevel.g.cs | 8 +- .../SoundPowerLevel.g.cs | 8 +- .../SoundPressureLevel.g.cs | 8 +- .../PhysicalConstants.g.cs | 185 +++++++++++++----- .../Acceleration1D.g.cs | 2 +- .../Acceleration2D.g.cs | 21 +- .../Acceleration3D.g.cs | 21 +- .../Acceleration4D.g.cs | 21 +- .../AccelerationMagnitude.g.cs | 4 +- .../AmountOfSubstance.g.cs | 8 +- .../Angle.g.cs | 4 +- .../AngularAcceleration1D.g.cs | 2 +- .../AngularAcceleration3D.g.cs | 21 +- .../AngularAccelerationMagnitude.g.cs | 4 +- .../AngularDisplacement3D.g.cs | 21 +- .../AngularJerk3D.g.cs | 19 +- .../AngularMomentum1D.g.cs | 2 +- .../AngularMomentum3D.g.cs | 21 +- .../AngularMomentumMagnitude.g.cs | 2 +- .../AngularSpeed.g.cs | 4 +- .../AngularVelocity1D.g.cs | 2 +- .../AngularVelocity3D.g.cs | 21 +- .../Area.g.cs | 2 +- .../Charge.g.cs | 2 +- .../ChargeMagnitude.g.cs | 8 +- .../Concentration.g.cs | 4 +- .../Current3D.g.cs | 19 +- .../CurrentMagnitude.g.cs | 4 +- .../Displacement1D.g.cs | 2 +- .../Displacement2D.g.cs | 21 +- .../Displacement3D.g.cs | 21 +- .../Displacement4D.g.cs | 21 +- .../DynamicViscosity.g.cs | 2 +- .../ElectricField2D.g.cs | 19 +- .../ElectricField3D.g.cs | 19 +- .../ElectricFlux.g.cs | 4 +- .../Energy.g.cs | 20 +- .../Entropy.g.cs | 4 +- .../Force2D.g.cs | 19 +- .../Force3D.g.cs | 19 +- .../Force4D.g.cs | 19 +- .../ForceMagnitude.g.cs | 10 +- .../GravitationalField3D.g.cs | 19 +- .../GravitationalParameter.g.cs | 4 +- .../HalfLife.g.cs | 24 +-- .../Jerk1D.g.cs | 2 +- .../Jerk2D.g.cs | 21 +- .../Jerk3D.g.cs | 21 +- .../Jerk4D.g.cs | 21 +- .../JerkMagnitude.g.cs | 4 +- .../Length.g.cs | 4 +- .../LuminousFlux.g.cs | 4 +- .../LuminousIntensity.g.cs | 4 +- .../MagneticFlux.g.cs | 10 +- .../MagneticFluxDensity3D.g.cs | 19 +- .../Mass.g.cs | 12 +- .../Momentum1D.g.cs | 2 +- .../Momentum2D.g.cs | 21 +- .../Momentum3D.g.cs | 21 +- .../Momentum4D.g.cs | 21 +- .../MomentumMagnitude.g.cs | 8 +- .../Period.g.cs | 24 +-- .../Position3D.g.cs | 19 +- .../Power.g.cs | 16 +- .../Ratio.g.cs | 8 +- .../SignedAngle.g.cs | 2 +- .../SignedRatio.g.cs | 2 +- .../Snap2D.g.cs | 19 +- .../Snap3D.g.cs | 19 +- .../Snap4D.g.cs | 19 +- .../SpecificAngularMomentum3D.g.cs | 19 +- .../Speed.g.cs | 8 +- .../ThrustVector.g.cs | 19 +- .../Torque3D.g.cs | 19 +- .../Translation3D.g.cs | 19 +- .../Velocity1D.g.cs | 2 +- .../Velocity2D.g.cs | 21 +- .../Velocity3D.g.cs | 21 +- .../Velocity4D.g.cs | 21 +- .../Voltage.g.cs | 4 +- .../VoltageMagnitude.g.cs | 12 +- .../Volume.g.cs | 8 +- .../Wavelength.g.cs | 24 +-- .../WeightVector.g.cs | 19 +- .../WindVelocity3D.g.cs | 19 +- Semantics.Quantities/LogarithmicStorage.cs | 85 ++++++++ Semantics.Quantities/StorageLiteral.cs | 63 ++++++ Semantics.Quantities/StorageMath.cs | 124 ++++++++++++ .../Generators/LogarithmicScalesGenerator.cs | 8 +- .../Generators/PhysicalConstantsGenerator.cs | 27 +-- .../Generators/QuantitiesGenerator.cs | 93 ++++++--- .../Metadata/domains.json | 14 +- .../Quantities/PhysicsBugfixTests.cs | 135 +++++++++++++ .../StorageMathPreciseAndVectorTests.cs | 88 +++++++++ 102 files changed, 1387 insertions(+), 600 deletions(-) create mode 100644 Semantics.Quantities/LogarithmicStorage.cs create mode 100644 Semantics.Test/Quantities/PhysicsBugfixTests.cs create mode 100644 Semantics.Test/Quantities/StorageMathPreciseAndVectorTests.cs diff --git a/CLAUDE.md b/CLAUDE.md index 186a2f19..e381cf09 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -298,12 +298,21 @@ PhysicalConstants.Generic.PlanckConstant() PhysicalConstants.Generic.DegreesPerRadian() ``` -Each constant is emitted as `T.Parse(literal, NumberStyles.Float, CultureInfo.InvariantCulture)` -into a private `Values` holder nested in its domain class, so the literal is parsed once per -closed generic type and the package needs no arbitrary-precision dependency. `NumberStyles.Float` -is mandatory, not incidental: several literals are in exponent form (`6.62607015e-34`, `20e-6`), -and the `Parse(string, IFormatProvider)` overload resolves to `NumberStyles.Number` for some -numeric types, which rejects an exponent. +Each constant is emitted as a property over its own lazily filled field in a private `Values` +holder nested in its domain class, filled by `StorageLiteral.Constant(literal, name)` the first +time it is read, so the literal is parsed once per constant and closed generic type and the package +needs no arbitrary-precision dependency. The literal is parsed with `NumberStyles.Float`, which is +mandatory, not incidental: several literals are in exponent form (`6.62607015e-34`, `20e-6`), and the +`Parse(string, IFormatProvider)` overload resolves to `NumberStyles.Number` for some numeric types, +which rejects an exponent. + +**Keep constants out of a shared initializer**, for the same reason as conversion factors below +(#392): with every constant of a domain in one static initializer, one literal `int` could not hold +made every constant of that domain throw `TypeInitializationException`, so `PH.Neutral` failed +because `GasConstant` has a fraction. Now a constant `T` cannot hold throws from its own accessor: +`OverflowException` when it is too large, and `ArithmeticException` when `T` keeps less than about six +significant digits of it (`StandardGravity` truncating to 9, `PlanckConstant` rounding +to zero). A whole number in range, such as `SpeedOfLight()`, works. ### Conversion factors and square roots at the storage type's precision @@ -347,13 +356,20 @@ converted with the 15 significant digits that conversion keeps. written outside the library needs nothing new. They are not named `Get…`, because CA1721 rejects a `GetToBaseFactor` method next to the `ToBaseFactor` property. -Vector `Length()` and `Distance()` call `StorageMath.Sqrt`. The binary floating point and integer -primitives take the `Math.Sqrt` round trip the generated code always inlined, so their results are -unchanged. Any other type is seeded from that root and refined with Newton steps in its own +Vector `Length()` and `Distance()` call `StorageMath.Hypot`, never a raw sum of squares (#327): the +two-component form is the public `Hypot`, and three and four components go through internal overloads +of it. A fractional type is scaled by its largest component first, so `Position3D` at 1e15 m +still has a length, and the primitives take `double.Hypot`, so an `int` component of 65536 no longer +squares to zero. `Normalize()` of a zero-length vector throws `DivideByZeroException`, as every +generated division by zero does (#480). The square root itself is `StorageMath.Sqrt`: the binary +floating point and integer primitives take the `Math.Sqrt` round trip. Any other type is seeded from that root and refined with Newton steps in its own arithmetic, so a `decimal` length has 28 significant digits. A value a `double` cannot hold, such as a `BigInteger` of 2^2048, is scaled by powers of four into [1, 4) for the seed, and the root is scaled back by the matching power of two. A root that does not settle throws `ArithmeticException` rather -than returning an estimate. The logarithmic scales and the hand-written audio types still compute +than returning an estimate. A type with no fixed precision, such as `PreciseNumber`, never settles, +because its products keep every digit and each Newton estimate doubles in length; `Cbrt` and `RootN` +stop it once a step moves the estimate by less than one part in 10^60 (#457), a tolerance a +fixed-precision type rounds to zero and so never sees. The logarithmic scales and the hand-written audio types still compute through `double`, and as of #235 every generated conversion says so in its own XML `` rather than only here — the method tooltip is where a `decimal` or `PreciseNumber` consumer spends the precision, so that is where the cost is stated. `SourceGeneratorTests` counts the remarks diff --git a/Semantics.Quantities/AudioEngineering/Decibels.cs b/Semantics.Quantities/AudioEngineering/Decibels.cs index 6a5f249a..a471dcaa 100644 --- a/Semantics.Quantities/AudioEngineering/Decibels.cs +++ b/Semantics.Quantities/AudioEngineering/Decibels.cs @@ -19,21 +19,23 @@ public readonly partial record struct Decibels /// Creates a level from a raw linear amplitude ratio using dB = 20·log10(ratio). /// /// The linear amplitude ratio. - /// A new . An amplitude of zero maps to negative infinity. + /// A new . An amplitude of zero maps to negative infinity where can hold it. + /// cannot hold the level, as for an amplitude of zero with or integer storage. public static Decibels FromAmplitude(T amplitude) { double linear = double.CreateChecked(amplitude); - return new(T.CreateChecked(20.0 * Math.Log10(linear))); + return new(LogarithmicStorage.FromLinear(20.0 * Math.Log10(linear), nameof(amplitude))); } /// /// Creates a level from a raw linear power ratio using dB = 10·log10(ratio). /// /// The linear power ratio. - /// A new . A power of zero maps to negative infinity. + /// A new . A power of zero maps to negative infinity where can hold it. + /// cannot hold the level, as for a power of zero with or integer storage. public static Decibels FromPower(T power) { double linear = double.CreateChecked(power); - return new(T.CreateChecked(10.0 * Math.Log10(linear))); + return new(LogarithmicStorage.FromLinear(10.0 * Math.Log10(linear), nameof(power))); } } diff --git a/Semantics.Quantities/AudioEngineering/Gain.cs b/Semantics.Quantities/AudioEngineering/Gain.cs index ebb54aec..43ab322a 100644 --- a/Semantics.Quantities/AudioEngineering/Gain.cs +++ b/Semantics.Quantities/AudioEngineering/Gain.cs @@ -34,7 +34,8 @@ public readonly partial record struct Gain /// /// Converts this gain to a level in decibels using the amplitude convention dB = 20·log10(gain). /// - /// The equivalent . Silence maps to negative infinity. + /// The equivalent . Silence maps to negative infinity where can hold it. + /// cannot hold the level, as for silence with or integer storage. public Decibels ToDecibels() => Decibels.FromGain(this); /// Multiplies two gains (cascading two stages). diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/Cents.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/Cents.g.cs index dcae4756..8450bde3 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/Cents.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/Cents.g.cs @@ -41,7 +41,7 @@ public readonly partial record struct Cents(T Value) : IComparable> /// Creates an interval from a frequency ratio using cents = 1200·log2(ratio). /// /// The linear . - /// A new . A linear value of zero maps to negative infinity. + /// A new . A linear value of zero maps to negative infinity where can hold it. /// /// Computes in whatever is: the value is /// converted to , the logarithm or power is taken there, and the @@ -49,10 +49,11 @@ public readonly partial record struct Cents(T Value) : IComparable> /// , or PreciseNumber — therefore keeps about fifteen /// significant digits across this conversion, rather than the precision it is capable of. /// + /// cannot hold the result, as for a linear value of zero with or integer storage. public static Cents FromFrequencyRatio(Ratio linear) { double linearValue = double.CreateChecked(linear.Value); - return new(T.CreateChecked(1200.0 * Math.Log2(linearValue))); + return new(LogarithmicStorage.FromLinear(1200.0 * Math.Log2(linearValue), nameof(linear))); } /// @@ -66,10 +67,11 @@ public static Cents FromFrequencyRatio(Ratio linear) /// , or PreciseNumber — therefore keeps about fifteen /// significant digits across this conversion, rather than the precision it is capable of. /// + /// cannot hold the linear value of a level this high. public Ratio ToFrequencyRatio() { double scaleValue = double.CreateChecked(Value); - return Ratio.Create(T.CreateChecked(Math.Pow(2.0, scaleValue / 1200.0))); + return Ratio.Create(LogarithmicStorage.ToLinear(Math.Pow(2.0, scaleValue / 1200.0))); } /// Adds two values in log space (cascading two linear stages multiplies them). diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/Decibels.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/Decibels.g.cs index 126e8fa9..81c0e151 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/Decibels.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/Decibels.g.cs @@ -41,7 +41,7 @@ public readonly partial record struct Decibels(T Value) : IComparable /// The linear . - /// A new . A linear value of zero maps to negative infinity. + /// A new . A linear value of zero maps to negative infinity where can hold it. /// /// Computes in whatever is: the value is /// converted to , the logarithm or power is taken there, and the @@ -49,10 +49,11 @@ public readonly partial record struct Decibels(T Value) : IComparable, or PreciseNumber — therefore keeps about fifteen /// significant digits across this conversion, rather than the precision it is capable of. /// + /// cannot hold the result, as for a linear value of zero with or integer storage. public static Decibels FromGain(Gain linear) { double linearValue = double.CreateChecked(linear.Value); - return new(T.CreateChecked(20.0 * Math.Log10(linearValue))); + return new(LogarithmicStorage.FromLinear(20.0 * Math.Log10(linearValue), nameof(linear))); } /// @@ -66,17 +67,18 @@ public static Decibels FromGain(Gain linear) /// , or PreciseNumber — therefore keeps about fifteen /// significant digits across this conversion, rather than the precision it is capable of. /// + /// cannot hold the linear value of a level this high. public Gain ToAmplitude() { double scaleValue = double.CreateChecked(Value); - return Gain.Create(T.CreateChecked(Math.Pow(10.0, scaleValue / 20.0))); + return Gain.Create(LogarithmicStorage.ToLinear(Math.Pow(10.0, scaleValue / 20.0))); } /// /// Creates a level from a linear power ratio using dB = 10·log10(ratio). /// /// The linear . - /// A new . A linear value of zero maps to negative infinity. + /// A new . A linear value of zero maps to negative infinity where can hold it. /// /// Computes in whatever is: the value is /// converted to , the logarithm or power is taken there, and the @@ -84,10 +86,11 @@ public Gain ToAmplitude() /// , or PreciseNumber — therefore keeps about fifteen /// significant digits across this conversion, rather than the precision it is capable of. /// + /// cannot hold the result, as for a linear value of zero with or integer storage. public static Decibels FromPowerRatio(Ratio linear) { double linearValue = double.CreateChecked(linear.Value); - return new(T.CreateChecked(10.0 * Math.Log10(linearValue))); + return new(LogarithmicStorage.FromLinear(10.0 * Math.Log10(linearValue), nameof(linear))); } /// @@ -101,10 +104,11 @@ public static Decibels FromPowerRatio(Ratio linear) /// , or PreciseNumber — therefore keeps about fifteen /// significant digits across this conversion, rather than the precision it is capable of. /// + /// cannot hold the linear value of a level this high. public Ratio ToPower() { double scaleValue = double.CreateChecked(Value); - return Ratio.Create(T.CreateChecked(Math.Pow(10.0, scaleValue / 10.0))); + return Ratio.Create(LogarithmicStorage.ToLinear(Math.Pow(10.0, scaleValue / 10.0))); } /// Adds two values in log space (cascading two linear stages multiplies them). diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/DirectionalityIndex.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/DirectionalityIndex.g.cs index 051f614a..d63369c2 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/DirectionalityIndex.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/DirectionalityIndex.g.cs @@ -41,7 +41,7 @@ public readonly partial record struct DirectionalityIndex(T Value) : ICompara /// Creates an index from the linear on-axis-to-average intensity ratio using DI = 10·log10(ratio). /// /// The linear . - /// A new . A linear value of zero maps to negative infinity. + /// A new . A linear value of zero maps to negative infinity where can hold it. /// /// Computes in whatever is: the value is /// converted to , the logarithm or power is taken there, and the @@ -49,10 +49,11 @@ public readonly partial record struct DirectionalityIndex(T Value) : ICompara /// , or PreciseNumber — therefore keeps about fifteen /// significant digits across this conversion, rather than the precision it is capable of. /// + /// cannot hold the result, as for a linear value of zero with or integer storage. public static DirectionalityIndex FromIntensityRatio(Ratio linear) { double linearValue = double.CreateChecked(linear.Value); - return new(T.CreateChecked(10.0 * Math.Log10(linearValue))); + return new(LogarithmicStorage.FromLinear(10.0 * Math.Log10(linearValue), nameof(linear))); } /// @@ -66,10 +67,11 @@ public static DirectionalityIndex FromIntensityRatio(Ratio linear) /// , or PreciseNumber — therefore keeps about fifteen /// significant digits across this conversion, rather than the precision it is capable of. /// + /// cannot hold the linear value of a level this high. public Ratio ToIntensityRatio() { double scaleValue = double.CreateChecked(Value); - return Ratio.Create(T.CreateChecked(Math.Pow(10.0, scaleValue / 10.0))); + return Ratio.Create(LogarithmicStorage.ToLinear(Math.Pow(10.0, scaleValue / 10.0))); } /// diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/PH.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/PH.g.cs index ba4dacc7..bf905936 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/PH.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/PH.g.cs @@ -41,7 +41,7 @@ public readonly partial record struct PH(T Value) : IComparable> /// Creates a pH from a hydrogen-ion concentration using pH = −log10([H⁺] in mol/L). /// /// The linear . - /// A new . A linear value of zero maps to negative infinity. + /// A new . A linear value of zero maps to negative infinity where can hold it. /// /// Computes in whatever is: the value is /// converted to , the logarithm or power is taken there, and the @@ -49,11 +49,12 @@ public readonly partial record struct PH(T Value) : IComparable> /// , or PreciseNumber — therefore keeps about fifteen /// significant digits across this conversion, rather than the precision it is capable of. /// + /// cannot hold the result, as for a linear value of zero with or integer storage. public static PH FromHydrogenConcentration(Concentration linear) { double linearValue = double.CreateChecked(linear.Value); double reference = 1000.0; - return new(T.CreateChecked(-1.0 * Math.Log10(linearValue / reference))); + return new(LogarithmicStorage.FromLinear(-1.0 * Math.Log10(linearValue / reference), nameof(linear))); } /// @@ -67,11 +68,12 @@ public static PH FromHydrogenConcentration(Concentration linear) /// , or PreciseNumber — therefore keeps about fifteen /// significant digits across this conversion, rather than the precision it is capable of. /// + /// cannot hold the linear value of a level this high. public Concentration ToHydrogenConcentration() { double scaleValue = double.CreateChecked(Value); double reference = 1000.0; - return Concentration.Create(T.CreateChecked(reference * Math.Pow(10.0, scaleValue / -1.0))); + return Concentration.Create(LogarithmicStorage.ToLinear(reference * Math.Pow(10.0, scaleValue / -1.0))); } /// diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/Semitones.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/Semitones.g.cs index b39fc7ce..1b082e3d 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/Semitones.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/Semitones.g.cs @@ -41,7 +41,7 @@ public readonly partial record struct Semitones(T Value) : IComparable /// The linear . - /// A new . A linear value of zero maps to negative infinity. + /// A new . A linear value of zero maps to negative infinity where can hold it. /// /// Computes in whatever is: the value is /// converted to , the logarithm or power is taken there, and the @@ -49,10 +49,11 @@ public readonly partial record struct Semitones(T Value) : IComparable, or PreciseNumber — therefore keeps about fifteen /// significant digits across this conversion, rather than the precision it is capable of. /// + /// cannot hold the result, as for a linear value of zero with or integer storage. public static Semitones FromFrequencyRatio(Ratio linear) { double linearValue = double.CreateChecked(linear.Value); - return new(T.CreateChecked(12.0 * Math.Log2(linearValue))); + return new(LogarithmicStorage.FromLinear(12.0 * Math.Log2(linearValue), nameof(linear))); } /// @@ -66,10 +67,11 @@ public static Semitones FromFrequencyRatio(Ratio linear) /// , or PreciseNumber — therefore keeps about fifteen /// significant digits across this conversion, rather than the precision it is capable of. /// + /// cannot hold the linear value of a level this high. public Ratio ToFrequencyRatio() { double scaleValue = double.CreateChecked(Value); - return Ratio.Create(T.CreateChecked(Math.Pow(2.0, scaleValue / 12.0))); + return Ratio.Create(LogarithmicStorage.ToLinear(Math.Pow(2.0, scaleValue / 12.0))); } /// Adds two values in log space (cascading two linear stages multiplies them). diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/SoundIntensityLevel.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/SoundIntensityLevel.g.cs index ef12bdca..3b714d5c 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/SoundIntensityLevel.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/SoundIntensityLevel.g.cs @@ -41,7 +41,7 @@ public readonly partial record struct SoundIntensityLevel(T Value) : ICompara /// Creates a level from a linear sound intensity using SIL = 10·log10(I / I₀). /// /// The linear . - /// A new . A linear value of zero maps to negative infinity. + /// A new . A linear value of zero maps to negative infinity where can hold it. /// /// Computes in whatever is: the value is /// converted to , the logarithm or power is taken there, and the @@ -49,11 +49,12 @@ public readonly partial record struct SoundIntensityLevel(T Value) : ICompara /// , or PreciseNumber — therefore keeps about fifteen /// significant digits across this conversion, rather than the precision it is capable of. /// + /// cannot hold the result, as for a linear value of zero with or integer storage. public static SoundIntensityLevel FromSoundIntensity(SoundIntensity linear) { double linearValue = double.CreateChecked(linear.Value); double reference = PhysicalConstants.Generic.ReferenceSoundIntensity(); - return new(T.CreateChecked(10.0 * Math.Log10(linearValue / reference))); + return new(LogarithmicStorage.FromLinear(10.0 * Math.Log10(linearValue / reference), nameof(linear))); } /// @@ -67,11 +68,12 @@ public static SoundIntensityLevel FromSoundIntensity(SoundIntensity linear /// , or PreciseNumber — therefore keeps about fifteen /// significant digits across this conversion, rather than the precision it is capable of. /// + /// cannot hold the linear value of a level this high. public SoundIntensity ToSoundIntensity() { double scaleValue = double.CreateChecked(Value); double reference = PhysicalConstants.Generic.ReferenceSoundIntensity(); - return SoundIntensity.Create(T.CreateChecked(reference * Math.Pow(10.0, scaleValue / 10.0))); + return SoundIntensity.Create(LogarithmicStorage.ToLinear(reference * Math.Pow(10.0, scaleValue / 10.0))); } /// Adds two values in log space (cascading two linear stages multiplies them). diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/SoundPowerLevel.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/SoundPowerLevel.g.cs index be113e4a..e1ffdd58 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/SoundPowerLevel.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/SoundPowerLevel.g.cs @@ -41,7 +41,7 @@ public readonly partial record struct SoundPowerLevel(T Value) : IComparable< /// Creates a level from a linear sound power using SWL = 10·log10(P / P₀). /// /// The linear . - /// A new . A linear value of zero maps to negative infinity. + /// A new . A linear value of zero maps to negative infinity where can hold it. /// /// Computes in whatever is: the value is /// converted to , the logarithm or power is taken there, and the @@ -49,11 +49,12 @@ public readonly partial record struct SoundPowerLevel(T Value) : IComparable< /// , or PreciseNumber — therefore keeps about fifteen /// significant digits across this conversion, rather than the precision it is capable of. /// + /// cannot hold the result, as for a linear value of zero with or integer storage. public static SoundPowerLevel FromSoundPower(SoundPower linear) { double linearValue = double.CreateChecked(linear.Value); double reference = PhysicalConstants.Generic.ReferenceSoundPower(); - return new(T.CreateChecked(10.0 * Math.Log10(linearValue / reference))); + return new(LogarithmicStorage.FromLinear(10.0 * Math.Log10(linearValue / reference), nameof(linear))); } /// @@ -67,11 +68,12 @@ public static SoundPowerLevel FromSoundPower(SoundPower linear) /// , or PreciseNumber — therefore keeps about fifteen /// significant digits across this conversion, rather than the precision it is capable of. /// + /// cannot hold the linear value of a level this high. public SoundPower ToSoundPower() { double scaleValue = double.CreateChecked(Value); double reference = PhysicalConstants.Generic.ReferenceSoundPower(); - return SoundPower.Create(T.CreateChecked(reference * Math.Pow(10.0, scaleValue / 10.0))); + return SoundPower.Create(LogarithmicStorage.ToLinear(reference * Math.Pow(10.0, scaleValue / 10.0))); } /// Adds two values in log space (cascading two linear stages multiplies them). diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/SoundPressureLevel.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/SoundPressureLevel.g.cs index e47b47c6..4012a8ee 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/SoundPressureLevel.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.LogarithmicScalesGenerator/SoundPressureLevel.g.cs @@ -41,7 +41,7 @@ public readonly partial record struct SoundPressureLevel(T Value) : IComparab /// Creates a level from a linear sound pressure using SPL = 20·log10(p / p₀). /// /// The linear . - /// A new . A linear value of zero maps to negative infinity. + /// A new . A linear value of zero maps to negative infinity where can hold it. /// /// Computes in whatever is: the value is /// converted to , the logarithm or power is taken there, and the @@ -49,11 +49,12 @@ public readonly partial record struct SoundPressureLevel(T Value) : IComparab /// , or PreciseNumber — therefore keeps about fifteen /// significant digits across this conversion, rather than the precision it is capable of. /// + /// cannot hold the result, as for a linear value of zero with or integer storage. public static SoundPressureLevel FromSoundPressure(SoundPressure linear) { double linearValue = double.CreateChecked(linear.Value); double reference = PhysicalConstants.Generic.ReferenceSoundPressure(); - return new(T.CreateChecked(20.0 * Math.Log10(linearValue / reference))); + return new(LogarithmicStorage.FromLinear(20.0 * Math.Log10(linearValue / reference), nameof(linear))); } /// @@ -67,11 +68,12 @@ public static SoundPressureLevel FromSoundPressure(SoundPressure linear) /// , or PreciseNumber — therefore keeps about fifteen /// significant digits across this conversion, rather than the precision it is capable of. /// + /// cannot hold the linear value of a level this high. public SoundPressure ToSoundPressure() { double scaleValue = double.CreateChecked(Value); double reference = PhysicalConstants.Generic.ReferenceSoundPressure(); - return SoundPressure.Create(T.CreateChecked(reference * Math.Pow(10.0, scaleValue / 20.0))); + return SoundPressure.Create(LogarithmicStorage.ToLinear(reference * Math.Pow(10.0, scaleValue / 20.0))); } /// Adds two values in log space (cascading two linear stages multiplies them). diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.PhysicalConstantsGenerator/PhysicalConstants.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.PhysicalConstantsGenerator/PhysicalConstants.g.cs index 5d01a603..f6c122a3 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.PhysicalConstantsGenerator/PhysicalConstants.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.PhysicalConstantsGenerator/PhysicalConstants.g.cs @@ -3,7 +3,6 @@ namespace ktsu.Semantics.Quantities; -using System.Globalization; using System.Numerics; /// @@ -36,16 +35,28 @@ private static class Values where T : struct, INumber { /// Reference sound intensity: 1 × 10⁻¹² W/m² (threshold of hearing) - internal static readonly T ReferenceSoundIntensity = T.Parse("1e-12", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T ReferenceSoundIntensity => cachedReferenceSoundIntensity ??= StorageLiteral.Constant("1e-12", "ReferenceSoundIntensity"); + + /// ReferenceSoundIntensity once materialised into . + private static T? cachedReferenceSoundIntensity; /// Reference sound power: 1 × 10⁻¹² W - internal static readonly T ReferenceSoundPower = T.Parse("1e-12", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T ReferenceSoundPower => cachedReferenceSoundPower ??= StorageLiteral.Constant("1e-12", "ReferenceSoundPower"); + + /// ReferenceSoundPower once materialised into . + private static T? cachedReferenceSoundPower; /// Reference sound pressure: 20 × 10⁻⁶ Pa (threshold of hearing) - internal static readonly T ReferenceSoundPressure = T.Parse("20e-6", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T ReferenceSoundPressure => cachedReferenceSoundPressure ??= StorageLiteral.Constant("20e-6", "ReferenceSoundPressure"); + + /// ReferenceSoundPressure once materialised into . + private static T? cachedReferenceSoundPressure; /// Sabine reverberation constant: 0.161 s/m - internal static readonly T SabineConstant = T.Parse("0.161", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T SabineConstant => cachedSabineConstant ??= StorageLiteral.Constant("0.161", "SabineConstant"); + + /// SabineConstant once materialised into . + private static T? cachedSabineConstant; } } @@ -70,13 +81,22 @@ private static class Values where T : struct, INumber { /// Degrees per radian: 180/π ≈ 57.29577951308232 (correctly rounded to 150 significant digits) - internal static readonly T DegreesPerRadian = T.Parse("57.2957795130823208767981548141051703324054724665643215491602438612028471483215526324409689958511109441862233816328648932814482646012483150360682678634", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T DegreesPerRadian => cachedDegreesPerRadian ??= StorageLiteral.Constant("57.2957795130823208767981548141051703324054724665643215491602438612028471483215526324409689958511109441862233816328648932814482646012483150360682678634", "DegreesPerRadian"); + + /// DegreesPerRadian once materialised into . + private static T? cachedDegreesPerRadian; /// Radians per degree: π/180 ≈ 0.017453292519943295 (correctly rounded to 150 significant digits) - internal static readonly T RadiansPerDegree = T.Parse("0.0174532925199432957692369076848861271344287188854172545609719144017100911460344944368224156963450948221230449250737905924838546922752810123984742189340", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T RadiansPerDegree => cachedRadiansPerDegree ??= StorageLiteral.Constant("0.0174532925199432957692369076848861271344287188854172545609719144017100911460344944368224156963450948221230449250737905924838546922752810123984742189340", "RadiansPerDegree"); + + /// RadiansPerDegree once materialised into . + private static T? cachedRadiansPerDegree; /// 2π, a full rotation in radians: 6.283185307179586 (correctly rounded to 150 significant digits) - internal static readonly T TwoPi = T.Parse("6.28318530717958647692528676655900576839433879875021164194988918461563281257241799725606965068423413596429617302656461329418768921910116446345071881626", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T TwoPi => cachedTwoPi ??= StorageLiteral.Constant("6.28318530717958647692528676655900576839433879875021164194988918461563281257241799725606965068423413596429617302656461329418768921910116446345071881626", "TwoPi"); + + /// TwoPi once materialised into . + private static T? cachedTwoPi; } } @@ -91,7 +111,7 @@ public static class Chemistry /// Natural logarithm of 2: 0.6931471805599453 public static T Ln2() where T : struct, INumber => Values.Ln2; - /// Molar volume of ideal gas at STP: 22.413969545014137 L/mol (calculated from R*T/P at 273.15K, 101325Pa) + /// Molar volume of ideal gas at STP: 0.022413969545014137 m³/mol, or 22.413969545014137 L/mol (calculated from R*T/P at 273.15K, 101325Pa) public static T MolarVolumeSTP() where T : struct, INumber => Values.MolarVolumeSTP; /// Neutral pH value at 25°C: 7.0 @@ -107,19 +127,34 @@ private static class Values where T : struct, INumber { /// Gas constant: 8.31446261815324 J/(mol·K) (exact, derived from Avogadro and Boltzmann constants) - internal static readonly T GasConstant = T.Parse("8.31446261815324", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T GasConstant => cachedGasConstant ??= StorageLiteral.Constant("8.31446261815324", "GasConstant"); + + /// GasConstant once materialised into . + private static T? cachedGasConstant; /// Natural logarithm of 2: 0.6931471805599453 - internal static readonly T Ln2 = T.Parse("0.6931471805599453094172321214581765680755001343602552541206800094933936219696947156058633269964186875420014810205706857336855202357581305570326707", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T Ln2 => cachedLn2 ??= StorageLiteral.Constant("0.6931471805599453094172321214581765680755001343602552541206800094933936219696947156058633269964186875420014810205706857336855202357581305570326707", "Ln2"); - /// Molar volume of ideal gas at STP: 22.413969545014137 L/mol (calculated from R*T/P at 273.15K, 101325Pa) - internal static readonly T MolarVolumeSTP = T.Parse("22.413969545014137", NumberStyles.Float, CultureInfo.InvariantCulture); + /// Ln2 once materialised into . + private static T? cachedLn2; + + /// Molar volume of ideal gas at STP: 0.022413969545014137 m³/mol, or 22.413969545014137 L/mol (calculated from R*T/P at 273.15K, 101325Pa) + internal static T MolarVolumeSTP => cachedMolarVolumeSTP ??= StorageLiteral.Constant("0.022413969545014137", "MolarVolumeSTP"); + + /// MolarVolumeSTP once materialised into . + private static T? cachedMolarVolumeSTP; /// Neutral pH value at 25°C: 7.0 - internal static readonly T NeutralPH = T.Parse("7.0", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T NeutralPH => cachedNeutralPH ??= StorageLiteral.Constant("7.0", "NeutralPH"); + + /// NeutralPH once materialised into . + private static T? cachedNeutralPH; /// Water ion product (Kw) at 25°C: 1.0 × 10⁻¹⁴ (pKw = 14.0) - internal static readonly T WaterIonProduct = T.Parse("14.0", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T WaterIonProduct => cachedWaterIonProduct ??= StorageLiteral.Constant("1.0e-14", "WaterIonProduct"); + + /// WaterIonProduct once materialised into . + private static T? cachedWaterIonProduct; } } @@ -141,10 +176,16 @@ private static class Values where T : struct, INumber { /// Standard atmospheric pressure: 101,325 Pa (exact by definition) - internal static readonly T StandardAtmosphericPressure = T.Parse("101325", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T StandardAtmosphericPressure => cachedStandardAtmosphericPressure ??= StorageLiteral.Constant("101325", "StandardAtmosphericPressure"); + + /// StandardAtmosphericPressure once materialised into . + private static T? cachedStandardAtmosphericPressure; /// Standard gravitational acceleration: 9.80665 m/s² (exact by definition) - internal static readonly T StandardGravity = T.Parse("9.80665", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T StandardGravity => cachedStandardGravity ??= StorageLiteral.Constant("9.80665", "StandardGravity"); + + /// StandardGravity once materialised into . + private static T? cachedStandardGravity; } } @@ -166,10 +207,16 @@ private static class Values where T : struct, INumber { /// Standard air density at 15°C and 1 atm: 1.225 kg/m³ (ISO 2533) - internal static readonly T StandardAirDensity = T.Parse("1.225", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T StandardAirDensity => cachedStandardAirDensity ??= StorageLiteral.Constant("1.225", "StandardAirDensity"); + + /// StandardAirDensity once materialised into . + private static T? cachedStandardAirDensity; /// Water surface tension at 20°C: 0.0728 N/m (NIST) - internal static readonly T WaterSurfaceTension = T.Parse("0.0728", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T WaterSurfaceTension => cachedWaterSurfaceTension ??= StorageLiteral.Constant("0.0728", "WaterSurfaceTension"); + + /// WaterSurfaceTension once materialised into . + private static T? cachedWaterSurfaceTension; } } @@ -193,10 +240,10 @@ public static class Fundamental /// Gravitational constant: 6.67430 × 10⁻¹¹ m³/(kg⋅s²) (2018 CODATA) public static T GravitationalConstant() where T : struct, INumber => Values.GravitationalConstant; - /// Magnetic permeability of free space: 4π × 10⁻⁷ H/m (exact by definition) + /// Magnetic permeability of free space: 1.25663706212 × 10⁻⁶ H/m (CODATA 2018; close to but no longer exactly 4π × 10⁻⁷ since the 2019 SI redefinition) public static T PermeabilityOfFreeSpace() where T : struct, INumber => Values.PermeabilityOfFreeSpace; - /// Electric permittivity of free space: 8.8541878128 × 10⁻¹² F/m (exact, derived) + /// Electric permittivity of free space: 8.8541878128 × 10⁻¹² F/m (CODATA 2018; measured, not exact, since the 2019 SI redefinition) public static T PermittivityOfFreeSpace() where T : struct, INumber => Values.PermittivityOfFreeSpace; /// Planck constant: 6.62607015 × 10⁻³⁴ J·s (exact, SI defining constant) @@ -212,31 +259,58 @@ private static class Values where T : struct, INumber { /// Avogadro's number: 6.02214076 × 10²³ entities/mol (exact, SI defining constant) - internal static readonly T AvogadroNumber = T.Parse("6.02214076e23", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T AvogadroNumber => cachedAvogadroNumber ??= StorageLiteral.Constant("6.02214076e23", "AvogadroNumber"); + + /// AvogadroNumber once materialised into . + private static T? cachedAvogadroNumber; /// Boltzmann constant: 1.380649 × 10⁻²³ J/K (exact, SI defining constant) - internal static readonly T BoltzmannConstant = T.Parse("1.380649e-23", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T BoltzmannConstant => cachedBoltzmannConstant ??= StorageLiteral.Constant("1.380649e-23", "BoltzmannConstant"); + + /// BoltzmannConstant once materialised into . + private static T? cachedBoltzmannConstant; /// Elementary charge: 1.602176634 × 10⁻¹⁹ C (exact, SI defining constant) - internal static readonly T ElementaryCharge = T.Parse("1.602176634e-19", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T ElementaryCharge => cachedElementaryCharge ??= StorageLiteral.Constant("1.602176634e-19", "ElementaryCharge"); + + /// ElementaryCharge once materialised into . + private static T? cachedElementaryCharge; /// Fine structure constant: 7.2973525693 × 10⁻³ (dimensionless, 2018 CODATA) - internal static readonly T FineStructureConstant = T.Parse("7.2973525693e-3", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T FineStructureConstant => cachedFineStructureConstant ??= StorageLiteral.Constant("7.2973525693e-3", "FineStructureConstant"); + + /// FineStructureConstant once materialised into . + private static T? cachedFineStructureConstant; /// Gravitational constant: 6.67430 × 10⁻¹¹ m³/(kg⋅s²) (2018 CODATA) - internal static readonly T GravitationalConstant = T.Parse("6.67430e-11", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T GravitationalConstant => cachedGravitationalConstant ??= StorageLiteral.Constant("6.67430e-11", "GravitationalConstant"); - /// Magnetic permeability of free space: 4π × 10⁻⁷ H/m (exact by definition) - internal static readonly T PermeabilityOfFreeSpace = T.Parse("1.25663706212e-6", NumberStyles.Float, CultureInfo.InvariantCulture); + /// GravitationalConstant once materialised into . + private static T? cachedGravitationalConstant; - /// Electric permittivity of free space: 8.8541878128 × 10⁻¹² F/m (exact, derived) - internal static readonly T PermittivityOfFreeSpace = T.Parse("8.8541878128e-12", NumberStyles.Float, CultureInfo.InvariantCulture); + /// Magnetic permeability of free space: 1.25663706212 × 10⁻⁶ H/m (CODATA 2018; close to but no longer exactly 4π × 10⁻⁷ since the 2019 SI redefinition) + internal static T PermeabilityOfFreeSpace => cachedPermeabilityOfFreeSpace ??= StorageLiteral.Constant("1.25663706212e-6", "PermeabilityOfFreeSpace"); + + /// PermeabilityOfFreeSpace once materialised into . + private static T? cachedPermeabilityOfFreeSpace; + + /// Electric permittivity of free space: 8.8541878128 × 10⁻¹² F/m (CODATA 2018; measured, not exact, since the 2019 SI redefinition) + internal static T PermittivityOfFreeSpace => cachedPermittivityOfFreeSpace ??= StorageLiteral.Constant("8.8541878128e-12", "PermittivityOfFreeSpace"); + + /// PermittivityOfFreeSpace once materialised into . + private static T? cachedPermittivityOfFreeSpace; /// Planck constant: 6.62607015 × 10⁻³⁴ J·s (exact, SI defining constant) - internal static readonly T PlanckConstant = T.Parse("6.62607015e-34", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T PlanckConstant => cachedPlanckConstant ??= StorageLiteral.Constant("6.62607015e-34", "PlanckConstant"); + + /// PlanckConstant once materialised into . + private static T? cachedPlanckConstant; /// Speed of light in vacuum: 299,792,458 m/s (exact, SI defining constant) - internal static readonly T SpeedOfLight = T.Parse("299792458", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T SpeedOfLight => cachedSpeedOfLight ??= StorageLiteral.Constant("299792458", "SpeedOfLight"); + + /// SpeedOfLight once materialised into . + private static T? cachedSpeedOfLight; } } @@ -258,10 +332,16 @@ private static class Values where T : struct, INumber { /// Atomic mass unit: 1.66053906660 × 10⁻²⁷ kg (2018 CODATA) - internal static readonly T AtomicMassUnit = T.Parse("1.66053906660e-27", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T AtomicMassUnit => cachedAtomicMassUnit ??= StorageLiteral.Constant("1.66053906660e-27", "AtomicMassUnit"); + + /// AtomicMassUnit once materialised into . + private static T? cachedAtomicMassUnit; /// Nuclear magneton: 5.0507837461 × 10⁻²⁷ J/T (2018 CODATA) - internal static readonly T NuclearMagneton = T.Parse("5.0507837461e-27", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T NuclearMagneton => cachedNuclearMagneton ??= StorageLiteral.Constant("5.0507837461e-27", "NuclearMagneton"); + + /// NuclearMagneton once materialised into . + private static T? cachedNuclearMagneton; } } @@ -280,7 +360,10 @@ private static class Values where T : struct, INumber { /// Luminous efficacy of monochromatic radiation at 540 THz: 683 lm/W (exact, SI defining constant) - internal static readonly T LuminousEfficacy = T.Parse("683.0", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T LuminousEfficacy => cachedLuminousEfficacy ??= StorageLiteral.Constant("683.0", "LuminousEfficacy"); + + /// LuminousEfficacy once materialised into . + private static T? cachedLuminousEfficacy; } } @@ -289,7 +372,7 @@ private static class Values /// public static class Thermodynamics { - /// Absolute zero in Celsius: 273.15 K (exact by definition) + /// Absolute zero in Celsius: −273.15 °C (exact by definition) public static T AbsoluteZeroInCelsius() where T : struct, INumber => Values.AbsoluteZeroInCelsius; /// Standard temperature (STP): 273.15 K (0°C) @@ -307,17 +390,29 @@ public static class Thermodynamics private static class Values where T : struct, INumber { - /// Absolute zero in Celsius: 273.15 K (exact by definition) - internal static readonly T AbsoluteZeroInCelsius = T.Parse("273.15", NumberStyles.Float, CultureInfo.InvariantCulture); + /// Absolute zero in Celsius: −273.15 °C (exact by definition) + internal static T AbsoluteZeroInCelsius => cachedAbsoluteZeroInCelsius ??= StorageLiteral.Constant("-273.15", "AbsoluteZeroInCelsius"); + + /// AbsoluteZeroInCelsius once materialised into . + private static T? cachedAbsoluteZeroInCelsius; /// Standard temperature (STP): 273.15 K (0°C) - internal static readonly T StandardTemperature = T.Parse("273.15", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T StandardTemperature => cachedStandardTemperature ??= StorageLiteral.Constant("273.15", "StandardTemperature"); + + /// StandardTemperature once materialised into . + private static T? cachedStandardTemperature; /// Water boiling point at 1 atm: 373.15 K (100°C) - internal static readonly T WaterBoilingPoint = T.Parse("373.15", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T WaterBoilingPoint => cachedWaterBoilingPoint ??= StorageLiteral.Constant("373.15", "WaterBoilingPoint"); + + /// WaterBoilingPoint once materialised into . + private static T? cachedWaterBoilingPoint; /// Water triple point: 273.16 K (exact by definition) - internal static readonly T WaterTriplePoint = T.Parse("273.16", NumberStyles.Float, CultureInfo.InvariantCulture); + internal static T WaterTriplePoint => cachedWaterTriplePoint ??= StorageLiteral.Constant("273.16", "WaterTriplePoint"); + + /// WaterTriplePoint once materialised into . + private static T? cachedWaterTriplePoint; } } @@ -326,7 +421,7 @@ private static class Values /// public static class Generic { - /// Gets absolute zero in celsius: 273.15 k (exact by definition) as type T. + /// Gets absolute zero in celsius: −273.15 °c (exact by definition) as type T. public static T AbsoluteZeroInCelsius() where T : struct, INumber => Thermodynamics.AbsoluteZeroInCelsius(); /// Gets atomic mass unit: 1.66053906660 × 10⁻²⁷ kg (2018 codata) as type T. @@ -359,7 +454,7 @@ public static class Generic /// Gets luminous efficacy of monochromatic radiation at 540 thz: 683 lm/w (exact, si defining constant) as type T. public static T LuminousEfficacy() where T : struct, INumber => Optics.LuminousEfficacy(); - /// Gets molar volume of ideal gas at stp: 22.413969545014137 l/mol (calculated from r*t/p at 273.15k, 101325pa) as type T. + /// Gets molar volume of ideal gas at stp: 0.022413969545014137 m³/mol, or 22.413969545014137 l/mol (calculated from r*t/p at 273.15k, 101325pa) as type T. public static T MolarVolumeSTP() where T : struct, INumber => Chemistry.MolarVolumeSTP(); /// Gets neutral ph value at 25°c: 7.0 as type T. @@ -368,10 +463,10 @@ public static class Generic /// Gets nuclear magneton: 5.0507837461 × 10⁻²⁷ j/t (2018 codata) as type T. public static T NuclearMagneton() where T : struct, INumber => NuclearPhysics.NuclearMagneton(); - /// Gets magnetic permeability of free space: 4π × 10⁻⁷ h/m (exact by definition) as type T. + /// Gets magnetic permeability of free space: 1.25663706212 × 10⁻⁶ h/m (codata 2018; close to but no longer exactly 4π × 10⁻⁷ since the 2019 si redefinition) as type T. public static T PermeabilityOfFreeSpace() where T : struct, INumber => Fundamental.PermeabilityOfFreeSpace(); - /// Gets electric permittivity of free space: 8.8541878128 × 10⁻¹² f/m (exact, derived) as type T. + /// Gets electric permittivity of free space: 8.8541878128 × 10⁻¹² f/m (codata 2018; measured, not exact, since the 2019 si redefinition) as type T. public static T PermittivityOfFreeSpace() where T : struct, INumber => Fundamental.PermittivityOfFreeSpace(); /// Gets planck constant: 6.62607015 × 10⁻³⁴ j·s (exact, si defining constant) as type T. diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Acceleration1D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Acceleration1D.g.cs index 1b64150c..117fdb8e 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Acceleration1D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Acceleration1D.g.cs @@ -135,6 +135,6 @@ namespace ktsu.Semantics.Quantities; /// Divides Acceleration1D by Duration to produce Jerk1D. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Jerk1D operator /(Acceleration1D left, Duration right) => Jerk1D.Create(left.Quantity / right.Quantity); + public static Jerk1D operator /(Acceleration1D left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Jerk1D.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Acceleration2D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Acceleration2D.g.cs index e9956296..8d62f214 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Acceleration2D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Acceleration2D.g.cs @@ -60,11 +60,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y) In(global::ktsu.Semantics.Quantities.IAccelerationUnit unit) => (unit.FromBase(X), unit.FromBase(Y)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y); @@ -77,8 +74,7 @@ public T Distance(Acceleration2D other) { T dX = X - other.X; T dY = Y - other.Y; - T sum = (dX * dX) + (dY * dY); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY); } /// Calculates the squared distance between two vectors. @@ -90,9 +86,15 @@ public T DistanceSquared(Acceleration2D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Acceleration2D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len }; } @@ -109,7 +111,8 @@ public Acceleration2D Normalize() public static Acceleration2D operator *(T scalar, Acceleration2D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y }; /// Divides a vector by a scalar. - public static Acceleration2D operator /(Acceleration2D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar }; + /// is zero. + public static Acceleration2D operator /(Acceleration2D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar }; /// Negates a vector. public static Acceleration2D operator -(Acceleration2D vector) => new() { X = -vector.X, Y = -vector.Y }; @@ -117,6 +120,6 @@ public Acceleration2D Normalize() public static Velocity2D operator *(Acceleration2D left, Duration right) => new() { X = left.X * right.Value, Y = left.Y * right.Value }; /// Acceleration2D / Duration = Jerk2D. - public static Jerk2D operator /(Acceleration2D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value }; + public static Jerk2D operator /(Acceleration2D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value }; }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Acceleration3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Acceleration3D.g.cs index 2d564c71..293c019c 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Acceleration3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Acceleration3D.g.cs @@ -68,11 +68,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.IAccelerationUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -92,8 +89,7 @@ public T Distance(Acceleration3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -106,9 +102,15 @@ public T DistanceSquared(Acceleration3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Acceleration3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -125,7 +127,8 @@ public Acceleration3D Normalize() public static Acceleration3D operator *(T scalar, Acceleration3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static Acceleration3D operator /(Acceleration3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static Acceleration3D operator /(Acceleration3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static Acceleration3D operator -(Acceleration3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; @@ -133,6 +136,6 @@ public Acceleration3D Normalize() public static Velocity3D operator *(Acceleration3D left, Duration right) => new() { X = left.X * right.Value, Y = left.Y * right.Value, Z = left.Z * right.Value }; /// Acceleration3D / Duration = Jerk3D. - public static Jerk3D operator /(Acceleration3D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value }; + public static Jerk3D operator /(Acceleration3D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value }; }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Acceleration4D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Acceleration4D.g.cs index bb5c16e9..e9d990bc 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Acceleration4D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Acceleration4D.g.cs @@ -76,11 +76,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z, T W) In(global::ktsu.Semantics.Quantities.IAccelerationUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z), unit.FromBase(W)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z) + (W * W); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z, W); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z) + (W * W); @@ -95,8 +92,7 @@ public T Distance(Acceleration4D other) T dY = Y - other.Y; T dZ = Z - other.Z; T dW = W - other.W; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ) + (dW * dW); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ, dW); } /// Calculates the squared distance between two vectors. @@ -110,9 +106,15 @@ public T DistanceSquared(Acceleration4D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Acceleration4D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len, W = W / len }; } @@ -129,7 +131,8 @@ public Acceleration4D Normalize() public static Acceleration4D operator *(T scalar, Acceleration4D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z, W = scalar * vector.W }; /// Divides a vector by a scalar. - public static Acceleration4D operator /(Acceleration4D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar, W = vector.W / scalar }; + /// is zero. + public static Acceleration4D operator /(Acceleration4D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar, W = vector.W / scalar }; /// Negates a vector. public static Acceleration4D operator -(Acceleration4D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z, W = -vector.W }; @@ -137,6 +140,6 @@ public Acceleration4D Normalize() public static Velocity4D operator *(Acceleration4D left, Duration right) => new() { X = left.X * right.Value, Y = left.Y * right.Value, Z = left.Z * right.Value, W = left.W * right.Value }; /// Acceleration4D / Duration = Jerk4D. - public static Jerk4D operator /(Acceleration4D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value, W = left.W / right.Value }; + public static Jerk4D operator /(Acceleration4D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value, W = left.W / right.Value }; }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AccelerationMagnitude.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AccelerationMagnitude.g.cs index 5705be0b..69d7f11c 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AccelerationMagnitude.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AccelerationMagnitude.g.cs @@ -136,13 +136,13 @@ namespace ktsu.Semantics.Quantities; /// Divides AccelerationMagnitude by Duration to produce JerkMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static JerkMagnitude operator /(AccelerationMagnitude left, Duration right) => JerkMagnitude.Create(left.Quantity / right.Quantity); + public static JerkMagnitude operator /(AccelerationMagnitude left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : JerkMagnitude.Create(left.Quantity / right.Quantity); /// /// Divides AccelerationMagnitude by JerkMagnitude to produce Duration. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Duration operator /(AccelerationMagnitude left, JerkMagnitude right) => Duration.Create(left.Quantity / right.Quantity); + public static Duration operator /(AccelerationMagnitude left, JerkMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Duration.Create(left.Quantity / right.Quantity); /// /// Multiplies AccelerationMagnitude by Area to produce GravitationalParameter. diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AmountOfSubstance.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AmountOfSubstance.g.cs index e903fd61..9762e61c 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AmountOfSubstance.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AmountOfSubstance.g.cs @@ -132,13 +132,13 @@ namespace ktsu.Semantics.Quantities; /// Divides AmountOfSubstance by Volume to produce Concentration. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Concentration operator /(AmountOfSubstance left, Volume right) => Concentration.Create(left.Quantity / right.Quantity); + public static Concentration operator /(AmountOfSubstance left, Volume right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Concentration.Create(left.Quantity / right.Quantity); /// /// Divides AmountOfSubstance by Concentration to produce Volume. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Volume operator /(AmountOfSubstance left, Concentration right) => Volume.Create(left.Quantity / right.Quantity); + public static Volume operator /(AmountOfSubstance left, Concentration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Volume.Create(left.Quantity / right.Quantity); /// /// Multiplies AmountOfSubstance by MolarMass to produce Mass. @@ -150,13 +150,13 @@ namespace ktsu.Semantics.Quantities; /// Divides AmountOfSubstance by Duration to produce CatalyticActivity. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static CatalyticActivity operator /(AmountOfSubstance left, Duration right) => CatalyticActivity.Create(left.Quantity / right.Quantity); + public static CatalyticActivity operator /(AmountOfSubstance left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : CatalyticActivity.Create(left.Quantity / right.Quantity); /// /// Divides AmountOfSubstance by CatalyticActivity to produce Duration. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Duration operator /(AmountOfSubstance left, CatalyticActivity right) => Duration.Create(left.Quantity / right.Quantity); + public static Duration operator /(AmountOfSubstance left, CatalyticActivity right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Duration.Create(left.Quantity / right.Quantity); /// /// Multiplies AmountOfSubstance by MolarEnergy to produce Energy. diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Angle.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Angle.g.cs index a8722d60..6a509ce9 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Angle.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Angle.g.cs @@ -148,12 +148,12 @@ namespace ktsu.Semantics.Quantities; /// Divides Angle by Duration to produce AngularSpeed. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static AngularSpeed operator /(Angle left, Duration right) => AngularSpeed.Create(left.Quantity / right.Quantity); + public static AngularSpeed operator /(Angle left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : AngularSpeed.Create(left.Quantity / right.Quantity); /// /// Divides Angle by AngularSpeed to produce Duration. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Duration operator /(Angle left, AngularSpeed right) => Duration.Create(left.Quantity / right.Quantity); + public static Duration operator /(Angle left, AngularSpeed right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Duration.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularAcceleration1D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularAcceleration1D.g.cs index 737aa1cb..f9ce76ff 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularAcceleration1D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularAcceleration1D.g.cs @@ -128,6 +128,6 @@ namespace ktsu.Semantics.Quantities; /// Divides AngularAcceleration1D by Duration to produce AngularJerk1D. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static AngularJerk1D operator /(AngularAcceleration1D left, Duration right) => AngularJerk1D.Create(left.Quantity / right.Quantity); + public static AngularJerk1D operator /(AngularAcceleration1D left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : AngularJerk1D.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularAcceleration3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularAcceleration3D.g.cs index 852fd437..395f9b28 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularAcceleration3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularAcceleration3D.g.cs @@ -61,11 +61,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.IAngularAccelerationUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -85,8 +82,7 @@ public T Distance(AngularAcceleration3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -99,9 +95,15 @@ public T DistanceSquared(AngularAcceleration3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public AngularAcceleration3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -118,7 +120,8 @@ public AngularAcceleration3D Normalize() public static AngularAcceleration3D operator *(T scalar, AngularAcceleration3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static AngularAcceleration3D operator /(AngularAcceleration3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static AngularAcceleration3D operator /(AngularAcceleration3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static AngularAcceleration3D operator -(AngularAcceleration3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; @@ -126,6 +129,6 @@ public AngularAcceleration3D Normalize() public static AngularVelocity3D operator *(AngularAcceleration3D left, Duration right) => new() { X = left.X * right.Value, Y = left.Y * right.Value, Z = left.Z * right.Value }; /// AngularAcceleration3D / Duration = AngularJerk3D. - public static AngularJerk3D operator /(AngularAcceleration3D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value }; + public static AngularJerk3D operator /(AngularAcceleration3D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value }; }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularAccelerationMagnitude.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularAccelerationMagnitude.g.cs index 7787eedf..3b812e3f 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularAccelerationMagnitude.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularAccelerationMagnitude.g.cs @@ -122,12 +122,12 @@ namespace ktsu.Semantics.Quantities; /// Divides AngularAccelerationMagnitude by Duration to produce AngularJerkMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static AngularJerkMagnitude operator /(AngularAccelerationMagnitude left, Duration right) => AngularJerkMagnitude.Create(left.Quantity / right.Quantity); + public static AngularJerkMagnitude operator /(AngularAccelerationMagnitude left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : AngularJerkMagnitude.Create(left.Quantity / right.Quantity); /// /// Divides AngularAccelerationMagnitude by AngularJerkMagnitude to produce Duration. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Duration operator /(AngularAccelerationMagnitude left, AngularJerkMagnitude right) => Duration.Create(left.Quantity / right.Quantity); + public static Duration operator /(AngularAccelerationMagnitude left, AngularJerkMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Duration.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularDisplacement3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularDisplacement3D.g.cs index 15e834f1..b94a19ce 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularDisplacement3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularDisplacement3D.g.cs @@ -89,11 +89,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.IAngularDisplacementUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -113,8 +110,7 @@ public T Distance(AngularDisplacement3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -127,9 +123,15 @@ public T DistanceSquared(AngularDisplacement3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public AngularDisplacement3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -146,11 +148,12 @@ public AngularDisplacement3D Normalize() public static AngularDisplacement3D operator *(T scalar, AngularDisplacement3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static AngularDisplacement3D operator /(AngularDisplacement3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static AngularDisplacement3D operator /(AngularDisplacement3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static AngularDisplacement3D operator -(AngularDisplacement3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; /// AngularDisplacement3D / Duration = AngularVelocity3D. - public static AngularVelocity3D operator /(AngularDisplacement3D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value }; + public static AngularVelocity3D operator /(AngularDisplacement3D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value }; }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularJerk3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularJerk3D.g.cs index 71aba589..d710d19f 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularJerk3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularJerk3D.g.cs @@ -61,11 +61,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.IAngularJerkUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -85,8 +82,7 @@ public T Distance(AngularJerk3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -99,9 +95,15 @@ public T DistanceSquared(AngularJerk3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public AngularJerk3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -118,7 +120,8 @@ public AngularJerk3D Normalize() public static AngularJerk3D operator *(T scalar, AngularJerk3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static AngularJerk3D operator /(AngularJerk3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static AngularJerk3D operator /(AngularJerk3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static AngularJerk3D operator -(AngularJerk3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularMomentum1D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularMomentum1D.g.cs index fa8004a7..c8b7f936 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularMomentum1D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularMomentum1D.g.cs @@ -122,6 +122,6 @@ namespace ktsu.Semantics.Quantities; /// Divides AngularMomentum1D by Duration to produce Torque1D. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Torque1D operator /(AngularMomentum1D left, Duration right) => Torque1D.Create(left.Quantity / right.Quantity); + public static Torque1D operator /(AngularMomentum1D left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Torque1D.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularMomentum3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularMomentum3D.g.cs index 3c22ee5f..3e937dfc 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularMomentum3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularMomentum3D.g.cs @@ -61,11 +61,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.IAngularMomentumUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -85,8 +82,7 @@ public T Distance(AngularMomentum3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -99,9 +95,15 @@ public T DistanceSquared(AngularMomentum3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public AngularMomentum3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -118,11 +120,12 @@ public AngularMomentum3D Normalize() public static AngularMomentum3D operator *(T scalar, AngularMomentum3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static AngularMomentum3D operator /(AngularMomentum3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static AngularMomentum3D operator /(AngularMomentum3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static AngularMomentum3D operator -(AngularMomentum3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; /// AngularMomentum3D / Duration = Torque3D. - public static Torque3D operator /(AngularMomentum3D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value }; + public static Torque3D operator /(AngularMomentum3D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value }; }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularMomentumMagnitude.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularMomentumMagnitude.g.cs index 72f2afbe..d98f0570 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularMomentumMagnitude.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularMomentumMagnitude.g.cs @@ -116,6 +116,6 @@ namespace ktsu.Semantics.Quantities; /// Divides AngularMomentumMagnitude by Duration to produce TorqueMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static TorqueMagnitude operator /(AngularMomentumMagnitude left, Duration right) => TorqueMagnitude.Create(left.Quantity / right.Quantity); + public static TorqueMagnitude operator /(AngularMomentumMagnitude left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : TorqueMagnitude.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularSpeed.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularSpeed.g.cs index 8e346728..24a0815f 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularSpeed.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularSpeed.g.cs @@ -130,12 +130,12 @@ namespace ktsu.Semantics.Quantities; /// Divides AngularSpeed by Duration to produce AngularAccelerationMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static AngularAccelerationMagnitude operator /(AngularSpeed left, Duration right) => AngularAccelerationMagnitude.Create(left.Quantity / right.Quantity); + public static AngularAccelerationMagnitude operator /(AngularSpeed left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : AngularAccelerationMagnitude.Create(left.Quantity / right.Quantity); /// /// Divides AngularSpeed by AngularAccelerationMagnitude to produce Duration. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Duration operator /(AngularSpeed left, AngularAccelerationMagnitude right) => Duration.Create(left.Quantity / right.Quantity); + public static Duration operator /(AngularSpeed left, AngularAccelerationMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Duration.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularVelocity1D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularVelocity1D.g.cs index 314aba9a..f85e3d18 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularVelocity1D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularVelocity1D.g.cs @@ -135,6 +135,6 @@ namespace ktsu.Semantics.Quantities; /// Divides AngularVelocity1D by Duration to produce AngularAcceleration1D. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static AngularAcceleration1D operator /(AngularVelocity1D left, Duration right) => AngularAcceleration1D.Create(left.Quantity / right.Quantity); + public static AngularAcceleration1D operator /(AngularVelocity1D left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : AngularAcceleration1D.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularVelocity3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularVelocity3D.g.cs index 4bfb30ba..23720815 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularVelocity3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AngularVelocity3D.g.cs @@ -68,11 +68,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.IAngularVelocityUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -92,8 +89,7 @@ public T Distance(AngularVelocity3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -106,9 +102,15 @@ public T DistanceSquared(AngularVelocity3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public AngularVelocity3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -125,7 +127,8 @@ public AngularVelocity3D Normalize() public static AngularVelocity3D operator *(T scalar, AngularVelocity3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static AngularVelocity3D operator /(AngularVelocity3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static AngularVelocity3D operator /(AngularVelocity3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static AngularVelocity3D operator -(AngularVelocity3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; @@ -133,6 +136,6 @@ public AngularVelocity3D Normalize() public static AngularDisplacement3D operator *(AngularVelocity3D left, Duration right) => new() { X = left.X * right.Value, Y = left.Y * right.Value, Z = left.Z * right.Value }; /// AngularVelocity3D / Duration = AngularAcceleration3D. - public static AngularAcceleration3D operator /(AngularVelocity3D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value }; + public static AngularAcceleration3D operator /(AngularVelocity3D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value }; }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Area.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Area.g.cs index d3d081eb..be92a44b 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Area.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Area.g.cs @@ -172,7 +172,7 @@ namespace ktsu.Semantics.Quantities; /// Divides Area by Length to produce Length. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Length operator /(Area left, Length right) => Length.Create(left.Quantity / right.Quantity); + public static Length operator /(Area left, Length right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Length.Create(left.Quantity / right.Quantity); /// /// Multiplies Area by Length to produce Volume. diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Charge.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Charge.g.cs index 255a67da..c1f3bfdb 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Charge.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Charge.g.cs @@ -129,6 +129,6 @@ namespace ktsu.Semantics.Quantities; /// Divides Charge by Duration to produce Current1D. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Current1D operator /(Charge left, Duration right) => Current1D.Create(left.Quantity / right.Quantity); + public static Current1D operator /(Charge left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Current1D.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ChargeMagnitude.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ChargeMagnitude.g.cs index 1154b02a..a0f9d731 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ChargeMagnitude.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ChargeMagnitude.g.cs @@ -124,24 +124,24 @@ namespace ktsu.Semantics.Quantities; /// Divides ChargeMagnitude by Duration to produce CurrentMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static CurrentMagnitude operator /(ChargeMagnitude left, Duration right) => CurrentMagnitude.Create(left.Quantity / right.Quantity); + public static CurrentMagnitude operator /(ChargeMagnitude left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : CurrentMagnitude.Create(left.Quantity / right.Quantity); /// /// Divides ChargeMagnitude by CurrentMagnitude to produce Duration. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Duration operator /(ChargeMagnitude left, CurrentMagnitude right) => Duration.Create(left.Quantity / right.Quantity); + public static Duration operator /(ChargeMagnitude left, CurrentMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Duration.Create(left.Quantity / right.Quantity); /// /// Divides ChargeMagnitude by VoltageMagnitude to produce Capacitance. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Capacitance operator /(ChargeMagnitude left, VoltageMagnitude right) => Capacitance.Create(left.Quantity / right.Quantity); + public static Capacitance operator /(ChargeMagnitude left, VoltageMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Capacitance.Create(left.Quantity / right.Quantity); /// /// Divides ChargeMagnitude by Capacitance to produce VoltageMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static VoltageMagnitude operator /(ChargeMagnitude left, Capacitance right) => VoltageMagnitude.Create(left.Quantity / right.Quantity); + public static VoltageMagnitude operator /(ChargeMagnitude left, Capacitance right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : VoltageMagnitude.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Concentration.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Concentration.g.cs index b0436a0f..d99e666d 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Concentration.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Concentration.g.cs @@ -146,12 +146,12 @@ namespace ktsu.Semantics.Quantities; /// Divides Concentration by Duration to produce ReactionRate. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static ReactionRate operator /(Concentration left, Duration right) => ReactionRate.Create(left.Quantity / right.Quantity); + public static ReactionRate operator /(Concentration left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : ReactionRate.Create(left.Quantity / right.Quantity); /// /// Divides Concentration by ReactionRate to produce Duration. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Duration operator /(Concentration left, ReactionRate right) => Duration.Create(left.Quantity / right.Quantity); + public static Duration operator /(Concentration left, ReactionRate right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Duration.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Current3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Current3D.g.cs index 97bde74d..1724e3d2 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Current3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Current3D.g.cs @@ -75,11 +75,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.IElectricCurrentUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -99,8 +96,7 @@ public T Distance(Current3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -113,9 +109,15 @@ public T DistanceSquared(Current3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Current3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -132,7 +134,8 @@ public Current3D Normalize() public static Current3D operator *(T scalar, Current3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static Current3D operator /(Current3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static Current3D operator /(Current3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static Current3D operator -(Current3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/CurrentMagnitude.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/CurrentMagnitude.g.cs index b368a557..34d28808 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/CurrentMagnitude.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/CurrentMagnitude.g.cs @@ -150,13 +150,13 @@ namespace ktsu.Semantics.Quantities; /// Divides CurrentMagnitude by VoltageMagnitude to produce Conductance. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Conductance operator /(CurrentMagnitude left, VoltageMagnitude right) => Conductance.Create(left.Quantity / right.Quantity); + public static Conductance operator /(CurrentMagnitude left, VoltageMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Conductance.Create(left.Quantity / right.Quantity); /// /// Divides CurrentMagnitude by Conductance to produce VoltageMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static VoltageMagnitude operator /(CurrentMagnitude left, Conductance right) => VoltageMagnitude.Create(left.Quantity / right.Quantity); + public static VoltageMagnitude operator /(CurrentMagnitude left, Conductance right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : VoltageMagnitude.Create(left.Quantity / right.Quantity); /// /// Multiplies CurrentMagnitude by Inductance to produce MagneticFlux. diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement1D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement1D.g.cs index 2d4dbafb..f830b055 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement1D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement1D.g.cs @@ -199,6 +199,6 @@ namespace ktsu.Semantics.Quantities; /// Divides Displacement1D by Duration to produce Velocity1D. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Velocity1D operator /(Displacement1D left, Duration right) => Velocity1D.Create(left.Quantity / right.Quantity); + public static Velocity1D operator /(Displacement1D left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Velocity1D.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement2D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement2D.g.cs index 7022ee1e..a23a31a9 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement2D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement2D.g.cs @@ -120,11 +120,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y) In(global::ktsu.Semantics.Quantities.ILengthUnit unit) => (unit.FromBase(X), unit.FromBase(Y)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y); @@ -137,8 +134,7 @@ public T Distance(Displacement2D other) { T dX = X - other.X; T dY = Y - other.Y; - T sum = (dX * dX) + (dY * dY); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY); } /// Calculates the squared distance between two vectors. @@ -150,9 +146,15 @@ public T DistanceSquared(Displacement2D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Displacement2D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len }; } @@ -169,11 +171,12 @@ public Displacement2D Normalize() public static Displacement2D operator *(T scalar, Displacement2D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y }; /// Divides a vector by a scalar. - public static Displacement2D operator /(Displacement2D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar }; + /// is zero. + public static Displacement2D operator /(Displacement2D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar }; /// Negates a vector. public static Displacement2D operator -(Displacement2D vector) => new() { X = -vector.X, Y = -vector.Y }; /// Displacement2D / Duration = Velocity2D. - public static Velocity2D operator /(Displacement2D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value }; + public static Velocity2D operator /(Displacement2D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value }; }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement3D.g.cs index 8d2a3671..7eb23c81 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement3D.g.cs @@ -138,11 +138,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.ILengthUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -162,8 +159,7 @@ public T Distance(Displacement3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -176,9 +172,15 @@ public T DistanceSquared(Displacement3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Displacement3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -195,12 +197,13 @@ public Displacement3D Normalize() public static Displacement3D operator *(T scalar, Displacement3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static Displacement3D operator /(Displacement3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static Displacement3D operator /(Displacement3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static Displacement3D operator -(Displacement3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; /// Displacement3D / Duration = Velocity3D. - public static Velocity3D operator /(Displacement3D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value }; + public static Velocity3D operator /(Displacement3D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value }; /// Typed cross product: Displacement3D x Force3D = Torque3D. public Torque3D Cross(Force3D other) diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement4D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement4D.g.cs index 8677193c..dd4a49ac 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement4D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement4D.g.cs @@ -156,11 +156,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z, T W) In(global::ktsu.Semantics.Quantities.ILengthUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z), unit.FromBase(W)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z) + (W * W); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z, W); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z) + (W * W); @@ -175,8 +172,7 @@ public T Distance(Displacement4D other) T dY = Y - other.Y; T dZ = Z - other.Z; T dW = W - other.W; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ) + (dW * dW); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ, dW); } /// Calculates the squared distance between two vectors. @@ -190,9 +186,15 @@ public T DistanceSquared(Displacement4D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Displacement4D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len, W = W / len }; } @@ -209,11 +211,12 @@ public Displacement4D Normalize() public static Displacement4D operator *(T scalar, Displacement4D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z, W = scalar * vector.W }; /// Divides a vector by a scalar. - public static Displacement4D operator /(Displacement4D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar, W = vector.W / scalar }; + /// is zero. + public static Displacement4D operator /(Displacement4D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar, W = vector.W / scalar }; /// Negates a vector. public static Displacement4D operator -(Displacement4D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z, W = -vector.W }; /// Displacement4D / Duration = Velocity4D. - public static Velocity4D operator /(Displacement4D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value, W = left.W / right.Value }; + public static Velocity4D operator /(Displacement4D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value, W = left.W / right.Value }; }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/DynamicViscosity.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/DynamicViscosity.g.cs index 5767532e..ce8ad6d8 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/DynamicViscosity.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/DynamicViscosity.g.cs @@ -132,6 +132,6 @@ namespace ktsu.Semantics.Quantities; /// Divides DynamicViscosity by Density to produce KinematicViscosity. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static KinematicViscosity operator /(DynamicViscosity left, Density right) => KinematicViscosity.Create(left.Quantity / right.Quantity); + public static KinematicViscosity operator /(DynamicViscosity left, Density right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : KinematicViscosity.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricField2D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricField2D.g.cs index 6e0f032f..0984f704 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricField2D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricField2D.g.cs @@ -54,11 +54,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y) In(global::ktsu.Semantics.Quantities.IElectricFieldUnit unit) => (unit.FromBase(X), unit.FromBase(Y)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y); @@ -71,8 +68,7 @@ public T Distance(ElectricField2D other) { T dX = X - other.X; T dY = Y - other.Y; - T sum = (dX * dX) + (dY * dY); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY); } /// Calculates the squared distance between two vectors. @@ -84,9 +80,15 @@ public T DistanceSquared(ElectricField2D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public ElectricField2D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len }; } @@ -103,7 +105,8 @@ public ElectricField2D Normalize() public static ElectricField2D operator *(T scalar, ElectricField2D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y }; /// Divides a vector by a scalar. - public static ElectricField2D operator /(ElectricField2D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar }; + /// is zero. + public static ElectricField2D operator /(ElectricField2D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar }; /// Negates a vector. public static ElectricField2D operator -(ElectricField2D vector) => new() { X = -vector.X, Y = -vector.Y }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricField3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricField3D.g.cs index 4786625b..35d0968d 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricField3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricField3D.g.cs @@ -61,11 +61,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.IElectricFieldUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -85,8 +82,7 @@ public T Distance(ElectricField3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -99,9 +95,15 @@ public T DistanceSquared(ElectricField3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public ElectricField3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -118,7 +120,8 @@ public ElectricField3D Normalize() public static ElectricField3D operator *(T scalar, ElectricField3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static ElectricField3D operator /(ElectricField3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static ElectricField3D operator /(ElectricField3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static ElectricField3D operator -(ElectricField3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricFlux.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricFlux.g.cs index 2a0a7698..db023e88 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricFlux.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricFlux.g.cs @@ -116,12 +116,12 @@ namespace ktsu.Semantics.Quantities; /// Divides ElectricFlux by Area to produce ElectricFieldMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static ElectricFieldMagnitude operator /(ElectricFlux left, Area right) => ElectricFieldMagnitude.Create(left.Quantity / right.Quantity); + public static ElectricFieldMagnitude operator /(ElectricFlux left, Area right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : ElectricFieldMagnitude.Create(left.Quantity / right.Quantity); /// /// Divides ElectricFlux by ElectricFieldMagnitude to produce Area. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Area operator /(ElectricFlux left, ElectricFieldMagnitude right) => Area.Create(left.Quantity / right.Quantity); + public static Area operator /(ElectricFlux left, ElectricFieldMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Area.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Energy.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Energy.g.cs index 582e8e58..19367498 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Energy.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Energy.g.cs @@ -180,60 +180,60 @@ namespace ktsu.Semantics.Quantities; /// Divides Energy by Length to produce ForceMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static ForceMagnitude operator /(Energy left, Length right) => ForceMagnitude.Create(left.Quantity / right.Quantity); + public static ForceMagnitude operator /(Energy left, Length right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : ForceMagnitude.Create(left.Quantity / right.Quantity); /// /// Divides Energy by ForceMagnitude to produce Length. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Length operator /(Energy left, ForceMagnitude right) => Length.Create(left.Quantity / right.Quantity); + public static Length operator /(Energy left, ForceMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Length.Create(left.Quantity / right.Quantity); /// /// Divides Energy by Volume to produce Pressure. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Pressure operator /(Energy left, Volume right) => Pressure.Create(left.Quantity / right.Quantity); + public static Pressure operator /(Energy left, Volume right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Pressure.Create(left.Quantity / right.Quantity); /// /// Divides Energy by Pressure to produce Volume. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Volume operator /(Energy left, Pressure right) => Volume.Create(left.Quantity / right.Quantity); + public static Volume operator /(Energy left, Pressure right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Volume.Create(left.Quantity / right.Quantity); /// /// Divides Energy by Duration to produce Power. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Power operator /(Energy left, Duration right) => Power.Create(left.Quantity / right.Quantity); + public static Power operator /(Energy left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Power.Create(left.Quantity / right.Quantity); /// /// Divides Energy by Power to produce Duration. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Duration operator /(Energy left, Power right) => Duration.Create(left.Quantity / right.Quantity); + public static Duration operator /(Energy left, Power right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Duration.Create(left.Quantity / right.Quantity); /// /// Divides Energy by Temperature to produce Entropy. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Entropy operator /(Energy left, Temperature right) => Entropy.Create(left.Quantity / right.Quantity); + public static Entropy operator /(Energy left, Temperature right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Entropy.Create(left.Quantity / right.Quantity); /// /// Divides Energy by Entropy to produce Temperature. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Temperature operator /(Energy left, Entropy right) => Temperature.Create(left.Quantity / right.Quantity); + public static Temperature operator /(Energy left, Entropy right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Temperature.Create(left.Quantity / right.Quantity); /// /// Divides Energy by AmountOfSubstance to produce MolarEnergy. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static MolarEnergy operator /(Energy left, AmountOfSubstance right) => MolarEnergy.Create(left.Quantity / right.Quantity); + public static MolarEnergy operator /(Energy left, AmountOfSubstance right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : MolarEnergy.Create(left.Quantity / right.Quantity); /// /// Divides Energy by MolarEnergy to produce AmountOfSubstance. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static AmountOfSubstance operator /(Energy left, MolarEnergy right) => AmountOfSubstance.Create(left.Quantity / right.Quantity); + public static AmountOfSubstance operator /(Energy left, MolarEnergy right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : AmountOfSubstance.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Entropy.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Entropy.g.cs index 8ad959d1..18a5f5e5 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Entropy.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Entropy.g.cs @@ -122,12 +122,12 @@ namespace ktsu.Semantics.Quantities; /// Divides Entropy by Mass to produce SpecificHeat. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static SpecificHeat operator /(Entropy left, Mass right) => SpecificHeat.Create(left.Quantity / right.Quantity); + public static SpecificHeat operator /(Entropy left, Mass right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : SpecificHeat.Create(left.Quantity / right.Quantity); /// /// Divides Entropy by SpecificHeat to produce Mass. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Mass operator /(Entropy left, SpecificHeat right) => Mass.Create(left.Quantity / right.Quantity); + public static Mass operator /(Entropy left, SpecificHeat right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Mass.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Force2D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Force2D.g.cs index b7c3880c..2b4e3873 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Force2D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Force2D.g.cs @@ -72,11 +72,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y) In(global::ktsu.Semantics.Quantities.IForceUnit unit) => (unit.FromBase(X), unit.FromBase(Y)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y); @@ -89,8 +86,7 @@ public T Distance(Force2D other) { T dX = X - other.X; T dY = Y - other.Y; - T sum = (dX * dX) + (dY * dY); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY); } /// Calculates the squared distance between two vectors. @@ -102,9 +98,15 @@ public T DistanceSquared(Force2D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Force2D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len }; } @@ -121,7 +123,8 @@ public Force2D Normalize() public static Force2D operator *(T scalar, Force2D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y }; /// Divides a vector by a scalar. - public static Force2D operator /(Force2D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar }; + /// is zero. + public static Force2D operator /(Force2D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar }; /// Negates a vector. public static Force2D operator -(Force2D vector) => new() { X = -vector.X, Y = -vector.Y }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Force3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Force3D.g.cs index 06f2fe55..aa679fb2 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Force3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Force3D.g.cs @@ -82,11 +82,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.IForceUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -106,8 +103,7 @@ public T Distance(Force3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -120,9 +116,15 @@ public T DistanceSquared(Force3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Force3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -139,7 +141,8 @@ public Force3D Normalize() public static Force3D operator *(T scalar, Force3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static Force3D operator /(Force3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static Force3D operator /(Force3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static Force3D operator -(Force3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Force4D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Force4D.g.cs index 451e3730..b720e614 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Force4D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Force4D.g.cs @@ -92,11 +92,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z, T W) In(global::ktsu.Semantics.Quantities.IForceUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z), unit.FromBase(W)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z) + (W * W); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z, W); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z) + (W * W); @@ -111,8 +108,7 @@ public T Distance(Force4D other) T dY = Y - other.Y; T dZ = Z - other.Z; T dW = W - other.W; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ) + (dW * dW); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ, dW); } /// Calculates the squared distance between two vectors. @@ -126,9 +122,15 @@ public T DistanceSquared(Force4D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Force4D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len, W = W / len }; } @@ -145,7 +147,8 @@ public Force4D Normalize() public static Force4D operator *(T scalar, Force4D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z, W = scalar * vector.W }; /// Divides a vector by a scalar. - public static Force4D operator /(Force4D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar, W = vector.W / scalar }; + /// is zero. + public static Force4D operator /(Force4D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar, W = vector.W / scalar }; /// Negates a vector. public static Force4D operator -(Force4D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z, W = -vector.W }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ForceMagnitude.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ForceMagnitude.g.cs index 9f7f8c4f..2435794d 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ForceMagnitude.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ForceMagnitude.g.cs @@ -140,13 +140,13 @@ namespace ktsu.Semantics.Quantities; /// Divides ForceMagnitude by AccelerationMagnitude to produce Mass. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Mass operator /(ForceMagnitude left, AccelerationMagnitude right) => Mass.Create(left.Quantity / right.Quantity); + public static Mass operator /(ForceMagnitude left, AccelerationMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Mass.Create(left.Quantity / right.Quantity); /// /// Divides ForceMagnitude by Mass to produce AccelerationMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static AccelerationMagnitude operator /(ForceMagnitude left, Mass right) => AccelerationMagnitude.Create(left.Quantity / right.Quantity); + public static AccelerationMagnitude operator /(ForceMagnitude left, Mass right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : AccelerationMagnitude.Create(left.Quantity / right.Quantity); /// /// Multiplies ForceMagnitude by Length to produce Energy. @@ -170,18 +170,18 @@ namespace ktsu.Semantics.Quantities; /// Divides ForceMagnitude by Area to produce Pressure. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Pressure operator /(ForceMagnitude left, Area right) => Pressure.Create(left.Quantity / right.Quantity); + public static Pressure operator /(ForceMagnitude left, Area right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Pressure.Create(left.Quantity / right.Quantity); /// /// Divides ForceMagnitude by Length to produce SurfaceTension. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static SurfaceTension operator /(ForceMagnitude left, Length right) => SurfaceTension.Create(left.Quantity / right.Quantity); + public static SurfaceTension operator /(ForceMagnitude left, Length right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : SurfaceTension.Create(left.Quantity / right.Quantity); /// /// Divides ForceMagnitude by SurfaceTension to produce Length. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Length operator /(ForceMagnitude left, SurfaceTension right) => Length.Create(left.Quantity / right.Quantity); + public static Length operator /(ForceMagnitude left, SurfaceTension right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Length.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalField3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalField3D.g.cs index 3822e3eb..6423eb27 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalField3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalField3D.g.cs @@ -68,11 +68,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.IAccelerationUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -92,8 +89,7 @@ public T Distance(GravitationalField3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -106,9 +102,15 @@ public T DistanceSquared(GravitationalField3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public GravitationalField3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -125,7 +127,8 @@ public GravitationalField3D Normalize() public static GravitationalField3D operator *(T scalar, GravitationalField3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static GravitationalField3D operator /(GravitationalField3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static GravitationalField3D operator /(GravitationalField3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static GravitationalField3D operator -(GravitationalField3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalParameter.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalParameter.g.cs index cf5d68ee..783fd103 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalParameter.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalParameter.g.cs @@ -124,12 +124,12 @@ namespace ktsu.Semantics.Quantities; /// Divides GravitationalParameter by Area to produce AccelerationMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static AccelerationMagnitude operator /(GravitationalParameter left, Area right) => AccelerationMagnitude.Create(left.Quantity / right.Quantity); + public static AccelerationMagnitude operator /(GravitationalParameter left, Area right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : AccelerationMagnitude.Create(left.Quantity / right.Quantity); /// /// Divides GravitationalParameter by Length to produce SpecificEnergyMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static SpecificEnergyMagnitude operator /(GravitationalParameter left, Length right) => SpecificEnergyMagnitude.Create(left.Quantity / right.Quantity); + public static SpecificEnergyMagnitude operator /(GravitationalParameter left, Length right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : SpecificEnergyMagnitude.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HalfLife.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HalfLife.g.cs index 06d4271c..af1eae3e 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HalfLife.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HalfLife.g.cs @@ -54,17 +54,17 @@ namespace ktsu.Semantics.Quantities; [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static HalfLife operator +(HalfLife left, HalfLife right) => Create(left.Quantity + right.Quantity); - /// Scales a by a bare number. Throws when the number is negative. + /// Scales a by a bare number. Throws when the result is not positive. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static HalfLife operator *(HalfLife left, T right) => Create(Vector0Guards.EnsureNonNegative(left.Quantity * right, nameof(right))); + public static HalfLife operator *(HalfLife left, T right) => Create(Vector0Guards.EnsurePositive(left.Quantity * right, nameof(right))); - /// Scales a by a bare number. Throws when the number is negative. + /// Scales a by a bare number. Throws when the result is not positive. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static HalfLife operator *(T left, HalfLife right) => Create(Vector0Guards.EnsureNonNegative(left * right.Quantity, nameof(left))); + public static HalfLife operator *(T left, HalfLife right) => Create(Vector0Guards.EnsurePositive(left * right.Quantity, nameof(left))); - /// Divides a by a bare number. Throws when the number is negative. + /// Divides a by a bare number. Throws when the result is not positive. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static HalfLife operator /(HalfLife left, T right) => T.IsZero(right) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Create(Vector0Guards.EnsureNonNegative(left.Quantity / right, nameof(right))); + public static HalfLife operator /(HalfLife left, T right) => T.IsZero(right) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Create(Vector0Guards.EnsurePositive(left.Quantity / right, nameof(right))); /// Divides one by another, giving the bare ratio. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] @@ -173,14 +173,14 @@ namespace ktsu.Semantics.Quantities; /// Implicit conversion to Duration. public static implicit operator Duration(HalfLife value) => Duration.Create(value.Value); - /// Explicit conversion from Duration. - public static explicit operator HalfLife(Duration value) => Create(value.Value); + /// Explicit conversion from Duration. Throws when the value is zero, which a HalfLife cannot be. + public static explicit operator HalfLife(Duration value) => Create(Vector0Guards.EnsurePositive(value.Value, nameof(value))); - /// Creates a HalfLife from a Duration value. - public static HalfLife From(Duration value) => Create(value.Value); + /// Creates a HalfLife from a Duration value. Throws when the value is zero, which a HalfLife cannot be. + public static HalfLife From(Duration value) => Create(Vector0Guards.EnsurePositive(value.Value, nameof(value))); - /// Subtracts two HalfLife values, returning the absolute difference as a non-negative HalfLife. + /// Subtracts two HalfLife values, returning the absolute difference as a positive HalfLife. Throws when the two are equal, since a HalfLife cannot be zero; widen to first for a difference that may be. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static HalfLife operator -(HalfLife left, HalfLife right) => Create(T.Abs(left.Quantity - right.Quantity)); + public static HalfLife operator -(HalfLife left, HalfLife right) => Create(Vector0Guards.EnsurePositive(T.Abs(left.Quantity - right.Quantity), nameof(right))); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Jerk1D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Jerk1D.g.cs index 79757f9a..0dbefdd5 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Jerk1D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Jerk1D.g.cs @@ -128,6 +128,6 @@ namespace ktsu.Semantics.Quantities; /// Divides Jerk1D by Duration to produce Snap1D. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Snap1D operator /(Jerk1D left, Duration right) => Snap1D.Create(left.Quantity / right.Quantity); + public static Snap1D operator /(Jerk1D left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Snap1D.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Jerk2D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Jerk2D.g.cs index f8fba657..95a89900 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Jerk2D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Jerk2D.g.cs @@ -54,11 +54,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y) In(global::ktsu.Semantics.Quantities.IJerkUnit unit) => (unit.FromBase(X), unit.FromBase(Y)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y); @@ -71,8 +68,7 @@ public T Distance(Jerk2D other) { T dX = X - other.X; T dY = Y - other.Y; - T sum = (dX * dX) + (dY * dY); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY); } /// Calculates the squared distance between two vectors. @@ -84,9 +80,15 @@ public T DistanceSquared(Jerk2D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Jerk2D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len }; } @@ -103,7 +105,8 @@ public Jerk2D Normalize() public static Jerk2D operator *(T scalar, Jerk2D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y }; /// Divides a vector by a scalar. - public static Jerk2D operator /(Jerk2D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar }; + /// is zero. + public static Jerk2D operator /(Jerk2D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar }; /// Negates a vector. public static Jerk2D operator -(Jerk2D vector) => new() { X = -vector.X, Y = -vector.Y }; @@ -111,6 +114,6 @@ public Jerk2D Normalize() public static Acceleration2D operator *(Jerk2D left, Duration right) => new() { X = left.X * right.Value, Y = left.Y * right.Value }; /// Jerk2D / Duration = Snap2D. - public static Snap2D operator /(Jerk2D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value }; + public static Snap2D operator /(Jerk2D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value }; }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Jerk3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Jerk3D.g.cs index ea63b1cd..7bc8255a 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Jerk3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Jerk3D.g.cs @@ -61,11 +61,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.IJerkUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -85,8 +82,7 @@ public T Distance(Jerk3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -99,9 +95,15 @@ public T DistanceSquared(Jerk3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Jerk3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -118,7 +120,8 @@ public Jerk3D Normalize() public static Jerk3D operator *(T scalar, Jerk3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static Jerk3D operator /(Jerk3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static Jerk3D operator /(Jerk3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static Jerk3D operator -(Jerk3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; @@ -126,6 +129,6 @@ public Jerk3D Normalize() public static Acceleration3D operator *(Jerk3D left, Duration right) => new() { X = left.X * right.Value, Y = left.Y * right.Value, Z = left.Z * right.Value }; /// Jerk3D / Duration = Snap3D. - public static Snap3D operator /(Jerk3D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value }; + public static Snap3D operator /(Jerk3D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value }; }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Jerk4D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Jerk4D.g.cs index 0fce3653..32a2fcd7 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Jerk4D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Jerk4D.g.cs @@ -68,11 +68,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z, T W) In(global::ktsu.Semantics.Quantities.IJerkUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z), unit.FromBase(W)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z) + (W * W); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z, W); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z) + (W * W); @@ -87,8 +84,7 @@ public T Distance(Jerk4D other) T dY = Y - other.Y; T dZ = Z - other.Z; T dW = W - other.W; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ) + (dW * dW); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ, dW); } /// Calculates the squared distance between two vectors. @@ -102,9 +98,15 @@ public T DistanceSquared(Jerk4D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Jerk4D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len, W = W / len }; } @@ -121,7 +123,8 @@ public Jerk4D Normalize() public static Jerk4D operator *(T scalar, Jerk4D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z, W = scalar * vector.W }; /// Divides a vector by a scalar. - public static Jerk4D operator /(Jerk4D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar, W = vector.W / scalar }; + /// is zero. + public static Jerk4D operator /(Jerk4D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar, W = vector.W / scalar }; /// Negates a vector. public static Jerk4D operator -(Jerk4D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z, W = -vector.W }; @@ -129,6 +132,6 @@ public Jerk4D Normalize() public static Acceleration4D operator *(Jerk4D left, Duration right) => new() { X = left.X * right.Value, Y = left.Y * right.Value, Z = left.Z * right.Value, W = left.W * right.Value }; /// Jerk4D / Duration = Snap4D. - public static Snap4D operator /(Jerk4D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value, W = left.W / right.Value }; + public static Snap4D operator /(Jerk4D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value, W = left.W / right.Value }; }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/JerkMagnitude.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/JerkMagnitude.g.cs index c2a936db..d8753c04 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/JerkMagnitude.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/JerkMagnitude.g.cs @@ -122,12 +122,12 @@ namespace ktsu.Semantics.Quantities; /// Divides JerkMagnitude by Duration to produce SnapMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static SnapMagnitude operator /(JerkMagnitude left, Duration right) => SnapMagnitude.Create(left.Quantity / right.Quantity); + public static SnapMagnitude operator /(JerkMagnitude left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : SnapMagnitude.Create(left.Quantity / right.Quantity); /// /// Divides JerkMagnitude by SnapMagnitude to produce Duration. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Duration operator /(JerkMagnitude left, SnapMagnitude right) => Duration.Create(left.Quantity / right.Quantity); + public static Duration operator /(JerkMagnitude left, SnapMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Duration.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Length.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Length.g.cs index a55156d9..9ec4d362 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Length.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Length.g.cs @@ -216,13 +216,13 @@ namespace ktsu.Semantics.Quantities; /// Divides Length by Duration to produce Speed. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Speed operator /(Length left, Duration right) => Speed.Create(left.Quantity / right.Quantity); + public static Speed operator /(Length left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Speed.Create(left.Quantity / right.Quantity); /// /// Divides Length by Speed to produce Duration. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Duration operator /(Length left, Speed right) => Duration.Create(left.Quantity / right.Quantity); + public static Duration operator /(Length left, Speed right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Duration.Create(left.Quantity / right.Quantity); /// /// Multiplies Length by Frequency to produce Speed. diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/LuminousFlux.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/LuminousFlux.g.cs index dfb0f293..914ceb3a 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/LuminousFlux.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/LuminousFlux.g.cs @@ -116,12 +116,12 @@ namespace ktsu.Semantics.Quantities; /// Divides LuminousFlux by Area to produce Illuminance. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Illuminance operator /(LuminousFlux left, Area right) => Illuminance.Create(left.Quantity / right.Quantity); + public static Illuminance operator /(LuminousFlux left, Area right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Illuminance.Create(left.Quantity / right.Quantity); /// /// Divides LuminousFlux by Illuminance to produce Area. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Area operator /(LuminousFlux left, Illuminance right) => Area.Create(left.Quantity / right.Quantity); + public static Area operator /(LuminousFlux left, Illuminance right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Area.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/LuminousIntensity.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/LuminousIntensity.g.cs index 302ca4a5..4446317a 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/LuminousIntensity.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/LuminousIntensity.g.cs @@ -124,12 +124,12 @@ namespace ktsu.Semantics.Quantities; /// Divides LuminousIntensity by Area to produce Luminance. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Luminance operator /(LuminousIntensity left, Area right) => Luminance.Create(left.Quantity / right.Quantity); + public static Luminance operator /(LuminousIntensity left, Area right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Luminance.Create(left.Quantity / right.Quantity); /// /// Divides LuminousIntensity by Luminance to produce Area. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Area operator /(LuminousIntensity left, Luminance right) => Area.Create(left.Quantity / right.Quantity); + public static Area operator /(LuminousIntensity left, Luminance right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Area.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MagneticFlux.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MagneticFlux.g.cs index 41f2dc6f..397b2c30 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MagneticFlux.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MagneticFlux.g.cs @@ -116,30 +116,30 @@ namespace ktsu.Semantics.Quantities; /// Divides MagneticFlux by Area to produce MagneticFluxDensityMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static MagneticFluxDensityMagnitude operator /(MagneticFlux left, Area right) => MagneticFluxDensityMagnitude.Create(left.Quantity / right.Quantity); + public static MagneticFluxDensityMagnitude operator /(MagneticFlux left, Area right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : MagneticFluxDensityMagnitude.Create(left.Quantity / right.Quantity); /// /// Divides MagneticFlux by MagneticFluxDensityMagnitude to produce Area. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Area operator /(MagneticFlux left, MagneticFluxDensityMagnitude right) => Area.Create(left.Quantity / right.Quantity); + public static Area operator /(MagneticFlux left, MagneticFluxDensityMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Area.Create(left.Quantity / right.Quantity); /// /// Divides MagneticFlux by Duration to produce VoltageMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static VoltageMagnitude operator /(MagneticFlux left, Duration right) => VoltageMagnitude.Create(left.Quantity / right.Quantity); + public static VoltageMagnitude operator /(MagneticFlux left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : VoltageMagnitude.Create(left.Quantity / right.Quantity); /// /// Divides MagneticFlux by CurrentMagnitude to produce Inductance. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Inductance operator /(MagneticFlux left, CurrentMagnitude right) => Inductance.Create(left.Quantity / right.Quantity); + public static Inductance operator /(MagneticFlux left, CurrentMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Inductance.Create(left.Quantity / right.Quantity); /// /// Divides MagneticFlux by Inductance to produce CurrentMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static CurrentMagnitude operator /(MagneticFlux left, Inductance right) => CurrentMagnitude.Create(left.Quantity / right.Quantity); + public static CurrentMagnitude operator /(MagneticFlux left, Inductance right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : CurrentMagnitude.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MagneticFluxDensity3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MagneticFluxDensity3D.g.cs index 712ad5e9..5024d3ef 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MagneticFluxDensity3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MagneticFluxDensity3D.g.cs @@ -68,11 +68,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.IMagneticFluxDensityUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -92,8 +89,7 @@ public T Distance(MagneticFluxDensity3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -106,9 +102,15 @@ public T DistanceSquared(MagneticFluxDensity3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public MagneticFluxDensity3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -125,7 +127,8 @@ public MagneticFluxDensity3D Normalize() public static MagneticFluxDensity3D operator *(T scalar, MagneticFluxDensity3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static MagneticFluxDensity3D operator /(MagneticFluxDensity3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static MagneticFluxDensity3D operator /(MagneticFluxDensity3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static MagneticFluxDensity3D operator -(MagneticFluxDensity3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Mass.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Mass.g.cs index d0027771..b708f0fe 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Mass.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Mass.g.cs @@ -184,13 +184,13 @@ namespace ktsu.Semantics.Quantities; /// Divides Mass by Volume to produce Density. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Density operator /(Mass left, Volume right) => Density.Create(left.Quantity / right.Quantity); + public static Density operator /(Mass left, Volume right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Density.Create(left.Quantity / right.Quantity); /// /// Divides Mass by Density to produce Volume. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Volume operator /(Mass left, Density right) => Volume.Create(left.Quantity / right.Quantity); + public static Volume operator /(Mass left, Density right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Volume.Create(left.Quantity / right.Quantity); /// /// Multiplies Mass by SpecificHeat to produce Entropy. @@ -202,24 +202,24 @@ namespace ktsu.Semantics.Quantities; /// Divides Mass by Duration to produce MassFlowRate. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static MassFlowRate operator /(Mass left, Duration right) => MassFlowRate.Create(left.Quantity / right.Quantity); + public static MassFlowRate operator /(Mass left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : MassFlowRate.Create(left.Quantity / right.Quantity); /// /// Divides Mass by MassFlowRate to produce Duration. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Duration operator /(Mass left, MassFlowRate right) => Duration.Create(left.Quantity / right.Quantity); + public static Duration operator /(Mass left, MassFlowRate right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Duration.Create(left.Quantity / right.Quantity); /// /// Divides Mass by AmountOfSubstance to produce MolarMass. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static MolarMass operator /(Mass left, AmountOfSubstance right) => MolarMass.Create(left.Quantity / right.Quantity); + public static MolarMass operator /(Mass left, AmountOfSubstance right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : MolarMass.Create(left.Quantity / right.Quantity); /// /// Divides Mass by MolarMass to produce AmountOfSubstance. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static AmountOfSubstance operator /(Mass left, MolarMass right) => AmountOfSubstance.Create(left.Quantity / right.Quantity); + public static AmountOfSubstance operator /(Mass left, MolarMass right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : AmountOfSubstance.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Momentum1D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Momentum1D.g.cs index 96208902..a865b300 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Momentum1D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Momentum1D.g.cs @@ -122,6 +122,6 @@ namespace ktsu.Semantics.Quantities; /// Divides Momentum1D by Duration to produce Force1D. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Force1D operator /(Momentum1D left, Duration right) => Force1D.Create(left.Quantity / right.Quantity); + public static Force1D operator /(Momentum1D left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Force1D.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Momentum2D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Momentum2D.g.cs index bb089b35..ad961101 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Momentum2D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Momentum2D.g.cs @@ -54,11 +54,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y) In(global::ktsu.Semantics.Quantities.IMomentumUnit unit) => (unit.FromBase(X), unit.FromBase(Y)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y); @@ -71,8 +68,7 @@ public T Distance(Momentum2D other) { T dX = X - other.X; T dY = Y - other.Y; - T sum = (dX * dX) + (dY * dY); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY); } /// Calculates the squared distance between two vectors. @@ -84,9 +80,15 @@ public T DistanceSquared(Momentum2D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Momentum2D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len }; } @@ -103,11 +105,12 @@ public Momentum2D Normalize() public static Momentum2D operator *(T scalar, Momentum2D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y }; /// Divides a vector by a scalar. - public static Momentum2D operator /(Momentum2D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar }; + /// is zero. + public static Momentum2D operator /(Momentum2D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar }; /// Negates a vector. public static Momentum2D operator -(Momentum2D vector) => new() { X = -vector.X, Y = -vector.Y }; /// Momentum2D / Duration = Force2D. - public static Force2D operator /(Momentum2D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value }; + public static Force2D operator /(Momentum2D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value }; }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Momentum3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Momentum3D.g.cs index 6f45cf0f..76477ba6 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Momentum3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Momentum3D.g.cs @@ -61,11 +61,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.IMomentumUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -85,8 +82,7 @@ public T Distance(Momentum3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -99,9 +95,15 @@ public T DistanceSquared(Momentum3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Momentum3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -118,11 +120,12 @@ public Momentum3D Normalize() public static Momentum3D operator *(T scalar, Momentum3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static Momentum3D operator /(Momentum3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static Momentum3D operator /(Momentum3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static Momentum3D operator -(Momentum3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; /// Momentum3D / Duration = Force3D. - public static Force3D operator /(Momentum3D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value }; + public static Force3D operator /(Momentum3D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value }; }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Momentum4D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Momentum4D.g.cs index 96b46993..56699e21 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Momentum4D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Momentum4D.g.cs @@ -68,11 +68,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z, T W) In(global::ktsu.Semantics.Quantities.IMomentumUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z), unit.FromBase(W)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z) + (W * W); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z, W); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z) + (W * W); @@ -87,8 +84,7 @@ public T Distance(Momentum4D other) T dY = Y - other.Y; T dZ = Z - other.Z; T dW = W - other.W; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ) + (dW * dW); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ, dW); } /// Calculates the squared distance between two vectors. @@ -102,9 +98,15 @@ public T DistanceSquared(Momentum4D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Momentum4D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len, W = W / len }; } @@ -121,11 +123,12 @@ public Momentum4D Normalize() public static Momentum4D operator *(T scalar, Momentum4D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z, W = scalar * vector.W }; /// Divides a vector by a scalar. - public static Momentum4D operator /(Momentum4D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar, W = vector.W / scalar }; + /// is zero. + public static Momentum4D operator /(Momentum4D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar, W = vector.W / scalar }; /// Negates a vector. public static Momentum4D operator -(Momentum4D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z, W = -vector.W }; /// Momentum4D / Duration = Force4D. - public static Force4D operator /(Momentum4D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value, W = left.W / right.Value }; + public static Force4D operator /(Momentum4D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value, W = left.W / right.Value }; }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MomentumMagnitude.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MomentumMagnitude.g.cs index 21a8eeee..d1eb3d94 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MomentumMagnitude.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MomentumMagnitude.g.cs @@ -116,24 +116,24 @@ namespace ktsu.Semantics.Quantities; /// Divides MomentumMagnitude by Speed to produce Mass. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Mass operator /(MomentumMagnitude left, Speed right) => Mass.Create(left.Quantity / right.Quantity); + public static Mass operator /(MomentumMagnitude left, Speed right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Mass.Create(left.Quantity / right.Quantity); /// /// Divides MomentumMagnitude by Mass to produce Speed. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Speed operator /(MomentumMagnitude left, Mass right) => Speed.Create(left.Quantity / right.Quantity); + public static Speed operator /(MomentumMagnitude left, Mass right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Speed.Create(left.Quantity / right.Quantity); /// /// Divides MomentumMagnitude by Duration to produce ForceMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static ForceMagnitude operator /(MomentumMagnitude left, Duration right) => ForceMagnitude.Create(left.Quantity / right.Quantity); + public static ForceMagnitude operator /(MomentumMagnitude left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : ForceMagnitude.Create(left.Quantity / right.Quantity); /// /// Divides MomentumMagnitude by ForceMagnitude to produce Duration. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Duration operator /(MomentumMagnitude left, ForceMagnitude right) => Duration.Create(left.Quantity / right.Quantity); + public static Duration operator /(MomentumMagnitude left, ForceMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Duration.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Period.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Period.g.cs index 036d9228..2e3305bc 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Period.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Period.g.cs @@ -54,17 +54,17 @@ namespace ktsu.Semantics.Quantities; [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Period operator +(Period left, Period right) => Create(left.Quantity + right.Quantity); - /// Scales a by a bare number. Throws when the number is negative. + /// Scales a by a bare number. Throws when the result is not positive. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Period operator *(Period left, T right) => Create(Vector0Guards.EnsureNonNegative(left.Quantity * right, nameof(right))); + public static Period operator *(Period left, T right) => Create(Vector0Guards.EnsurePositive(left.Quantity * right, nameof(right))); - /// Scales a by a bare number. Throws when the number is negative. + /// Scales a by a bare number. Throws when the result is not positive. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Period operator *(T left, Period right) => Create(Vector0Guards.EnsureNonNegative(left * right.Quantity, nameof(left))); + public static Period operator *(T left, Period right) => Create(Vector0Guards.EnsurePositive(left * right.Quantity, nameof(left))); - /// Divides a by a bare number. Throws when the number is negative. + /// Divides a by a bare number. Throws when the result is not positive. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Period operator /(Period left, T right) => T.IsZero(right) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Create(Vector0Guards.EnsureNonNegative(left.Quantity / right, nameof(right))); + public static Period operator /(Period left, T right) => T.IsZero(right) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Create(Vector0Guards.EnsurePositive(left.Quantity / right, nameof(right))); /// Divides one by another, giving the bare ratio. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] @@ -173,14 +173,14 @@ namespace ktsu.Semantics.Quantities; /// Implicit conversion to Duration. public static implicit operator Duration(Period value) => Duration.Create(value.Value); - /// Explicit conversion from Duration. - public static explicit operator Period(Duration value) => Create(value.Value); + /// Explicit conversion from Duration. Throws when the value is zero, which a Period cannot be. + public static explicit operator Period(Duration value) => Create(Vector0Guards.EnsurePositive(value.Value, nameof(value))); - /// Creates a Period from a Duration value. - public static Period From(Duration value) => Create(value.Value); + /// Creates a Period from a Duration value. Throws when the value is zero, which a Period cannot be. + public static Period From(Duration value) => Create(Vector0Guards.EnsurePositive(value.Value, nameof(value))); - /// Subtracts two Period values, returning the absolute difference as a non-negative Period. + /// Subtracts two Period values, returning the absolute difference as a positive Period. Throws when the two are equal, since a Period cannot be zero; widen to first for a difference that may be. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Period operator -(Period left, Period right) => Create(T.Abs(left.Quantity - right.Quantity)); + public static Period operator -(Period left, Period right) => Create(Vector0Guards.EnsurePositive(T.Abs(left.Quantity - right.Quantity), nameof(right))); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Position3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Position3D.g.cs index 25f4b689..b1c46c47 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Position3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Position3D.g.cs @@ -138,11 +138,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.ILengthUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -162,8 +159,7 @@ public T Distance(Position3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -176,9 +172,15 @@ public T DistanceSquared(Position3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Position3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -195,7 +197,8 @@ public Position3D Normalize() public static Position3D operator *(T scalar, Position3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static Position3D operator /(Position3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static Position3D operator /(Position3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static Position3D operator -(Position3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Power.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Power.g.cs index e36096d7..5dcae160 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Power.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Power.g.cs @@ -140,25 +140,25 @@ namespace ktsu.Semantics.Quantities; /// Divides Power by VoltageMagnitude to produce CurrentMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static CurrentMagnitude operator /(Power left, VoltageMagnitude right) => CurrentMagnitude.Create(left.Quantity / right.Quantity); + public static CurrentMagnitude operator /(Power left, VoltageMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : CurrentMagnitude.Create(left.Quantity / right.Quantity); /// /// Divides Power by CurrentMagnitude to produce VoltageMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static VoltageMagnitude operator /(Power left, CurrentMagnitude right) => VoltageMagnitude.Create(left.Quantity / right.Quantity); + public static VoltageMagnitude operator /(Power left, CurrentMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : VoltageMagnitude.Create(left.Quantity / right.Quantity); /// /// Divides Power by Speed to produce ForceMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static ForceMagnitude operator /(Power left, Speed right) => ForceMagnitude.Create(left.Quantity / right.Quantity); + public static ForceMagnitude operator /(Power left, Speed right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : ForceMagnitude.Create(left.Quantity / right.Quantity); /// /// Divides Power by ForceMagnitude to produce Speed. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Speed operator /(Power left, ForceMagnitude right) => Speed.Create(left.Quantity / right.Quantity); + public static Speed operator /(Power left, ForceMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Speed.Create(left.Quantity / right.Quantity); /// /// Multiplies Power by Duration to produce Energy. @@ -170,24 +170,24 @@ namespace ktsu.Semantics.Quantities; /// Divides Power by Area to produce Irradiance. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Irradiance operator /(Power left, Area right) => Irradiance.Create(left.Quantity / right.Quantity); + public static Irradiance operator /(Power left, Area right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Irradiance.Create(left.Quantity / right.Quantity); /// /// Divides Power by Irradiance to produce Area. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Area operator /(Power left, Irradiance right) => Area.Create(left.Quantity / right.Quantity); + public static Area operator /(Power left, Irradiance right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Area.Create(left.Quantity / right.Quantity); /// /// Divides Power by Volume to produce ElectricPowerDensity. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static ElectricPowerDensity operator /(Power left, Volume right) => ElectricPowerDensity.Create(left.Quantity / right.Quantity); + public static ElectricPowerDensity operator /(Power left, Volume right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : ElectricPowerDensity.Create(left.Quantity / right.Quantity); /// /// Divides Power by ElectricPowerDensity to produce Volume. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Volume operator /(Power left, ElectricPowerDensity right) => Volume.Create(left.Quantity / right.Quantity); + public static Volume operator /(Power left, ElectricPowerDensity right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Volume.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Ratio.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Ratio.g.cs index ab24c2eb..daae2e90 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Ratio.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Ratio.g.cs @@ -200,24 +200,24 @@ namespace ktsu.Semantics.Quantities; /// Divides Ratio by Duration to produce Frequency. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Frequency operator /(Ratio left, Duration right) => Frequency.Create(left.Quantity / right.Quantity); + public static Frequency operator /(Ratio left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Frequency.Create(left.Quantity / right.Quantity); /// /// Divides Ratio by Frequency to produce Duration. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Duration operator /(Ratio left, Frequency right) => Duration.Create(left.Quantity / right.Quantity); + public static Duration operator /(Ratio left, Frequency right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Duration.Create(left.Quantity / right.Quantity); /// /// Divides Ratio by Temperature to produce ThermalExpansionCoefficient. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static ThermalExpansionCoefficient operator /(Ratio left, Temperature right) => ThermalExpansionCoefficient.Create(left.Quantity / right.Quantity); + public static ThermalExpansionCoefficient operator /(Ratio left, Temperature right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : ThermalExpansionCoefficient.Create(left.Quantity / right.Quantity); /// /// Divides Ratio by ThermalExpansionCoefficient to produce Temperature. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Temperature operator /(Ratio left, ThermalExpansionCoefficient right) => Temperature.Create(left.Quantity / right.Quantity); + public static Temperature operator /(Ratio left, ThermalExpansionCoefficient right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Temperature.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SignedAngle.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SignedAngle.g.cs index 36124ab7..d7f5823b 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SignedAngle.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SignedAngle.g.cs @@ -150,6 +150,6 @@ namespace ktsu.Semantics.Quantities; /// Divides SignedAngle by Duration to produce AngularVelocity1D. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static AngularVelocity1D operator /(SignedAngle left, Duration right) => AngularVelocity1D.Create(left.Quantity / right.Quantity); + public static AngularVelocity1D operator /(SignedAngle left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : AngularVelocity1D.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SignedRatio.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SignedRatio.g.cs index 75c3ee73..d12fc24a 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SignedRatio.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SignedRatio.g.cs @@ -191,6 +191,6 @@ namespace ktsu.Semantics.Quantities; /// Divides SignedRatio by Ratio to produce SignedRatio. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static SignedRatio operator /(SignedRatio left, Ratio right) => SignedRatio.Create(left.Quantity / right.Quantity); + public static SignedRatio operator /(SignedRatio left, Ratio right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : SignedRatio.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Snap2D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Snap2D.g.cs index 55f9a0b1..42896aa9 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Snap2D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Snap2D.g.cs @@ -54,11 +54,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y) In(global::ktsu.Semantics.Quantities.ISnapUnit unit) => (unit.FromBase(X), unit.FromBase(Y)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y); @@ -71,8 +68,7 @@ public T Distance(Snap2D other) { T dX = X - other.X; T dY = Y - other.Y; - T sum = (dX * dX) + (dY * dY); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY); } /// Calculates the squared distance between two vectors. @@ -84,9 +80,15 @@ public T DistanceSquared(Snap2D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Snap2D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len }; } @@ -103,7 +105,8 @@ public Snap2D Normalize() public static Snap2D operator *(T scalar, Snap2D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y }; /// Divides a vector by a scalar. - public static Snap2D operator /(Snap2D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar }; + /// is zero. + public static Snap2D operator /(Snap2D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar }; /// Negates a vector. public static Snap2D operator -(Snap2D vector) => new() { X = -vector.X, Y = -vector.Y }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Snap3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Snap3D.g.cs index 63d870a6..33a34384 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Snap3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Snap3D.g.cs @@ -61,11 +61,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.ISnapUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -85,8 +82,7 @@ public T Distance(Snap3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -99,9 +95,15 @@ public T DistanceSquared(Snap3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Snap3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -118,7 +120,8 @@ public Snap3D Normalize() public static Snap3D operator *(T scalar, Snap3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static Snap3D operator /(Snap3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static Snap3D operator /(Snap3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static Snap3D operator -(Snap3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Snap4D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Snap4D.g.cs index 67bd5d3b..a27dafcb 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Snap4D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Snap4D.g.cs @@ -68,11 +68,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z, T W) In(global::ktsu.Semantics.Quantities.ISnapUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z), unit.FromBase(W)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z) + (W * W); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z, W); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z) + (W * W); @@ -87,8 +84,7 @@ public T Distance(Snap4D other) T dY = Y - other.Y; T dZ = Z - other.Z; T dW = W - other.W; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ) + (dW * dW); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ, dW); } /// Calculates the squared distance between two vectors. @@ -102,9 +98,15 @@ public T DistanceSquared(Snap4D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Snap4D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len, W = W / len }; } @@ -121,7 +123,8 @@ public Snap4D Normalize() public static Snap4D operator *(T scalar, Snap4D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z, W = scalar * vector.W }; /// Divides a vector by a scalar. - public static Snap4D operator /(Snap4D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar, W = vector.W / scalar }; + /// is zero. + public static Snap4D operator /(Snap4D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar, W = vector.W / scalar }; /// Negates a vector. public static Snap4D operator -(Snap4D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z, W = -vector.W }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificAngularMomentum3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificAngularMomentum3D.g.cs index aab3c424..22f58fa4 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificAngularMomentum3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificAngularMomentum3D.g.cs @@ -61,11 +61,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.ISpecificAngularMomentumUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -85,8 +82,7 @@ public T Distance(SpecificAngularMomentum3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -99,9 +95,15 @@ public T DistanceSquared(SpecificAngularMomentum3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public SpecificAngularMomentum3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -118,7 +120,8 @@ public SpecificAngularMomentum3D Normalize() public static SpecificAngularMomentum3D operator *(T scalar, SpecificAngularMomentum3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static SpecificAngularMomentum3D operator /(SpecificAngularMomentum3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static SpecificAngularMomentum3D operator /(SpecificAngularMomentum3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static SpecificAngularMomentum3D operator -(SpecificAngularMomentum3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Speed.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Speed.g.cs index ecac9e04..03a77017 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Speed.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Speed.g.cs @@ -168,25 +168,25 @@ namespace ktsu.Semantics.Quantities; /// Divides Speed by Duration to produce AccelerationMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static AccelerationMagnitude operator /(Speed left, Duration right) => AccelerationMagnitude.Create(left.Quantity / right.Quantity); + public static AccelerationMagnitude operator /(Speed left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : AccelerationMagnitude.Create(left.Quantity / right.Quantity); /// /// Divides Speed by AccelerationMagnitude to produce Duration. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Duration operator /(Speed left, AccelerationMagnitude right) => Duration.Create(left.Quantity / right.Quantity); + public static Duration operator /(Speed left, AccelerationMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Duration.Create(left.Quantity / right.Quantity); /// /// Divides Speed by Length to produce Frequency. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Frequency operator /(Speed left, Length right) => Frequency.Create(left.Quantity / right.Quantity); + public static Frequency operator /(Speed left, Length right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Frequency.Create(left.Quantity / right.Quantity); /// /// Divides Speed by Frequency to produce Length. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Length operator /(Speed left, Frequency right) => Length.Create(left.Quantity / right.Quantity); + public static Length operator /(Speed left, Frequency right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Length.Create(left.Quantity / right.Quantity); /// /// Multiplies Speed by ForceMagnitude to produce Power. diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ThrustVector.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ThrustVector.g.cs index bedd85b8..eb121302 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ThrustVector.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ThrustVector.g.cs @@ -82,11 +82,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.IForceUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -106,8 +103,7 @@ public T Distance(ThrustVector other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -120,9 +116,15 @@ public T DistanceSquared(ThrustVector other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public ThrustVector Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -139,7 +141,8 @@ public ThrustVector Normalize() public static ThrustVector operator *(T scalar, ThrustVector vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static ThrustVector operator /(ThrustVector vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static ThrustVector operator /(ThrustVector vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static ThrustVector operator -(ThrustVector vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Torque3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Torque3D.g.cs index 20b025c5..9e340607 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Torque3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Torque3D.g.cs @@ -68,11 +68,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.ITorqueUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -92,8 +89,7 @@ public T Distance(Torque3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -106,9 +102,15 @@ public T DistanceSquared(Torque3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Torque3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -125,7 +127,8 @@ public Torque3D Normalize() public static Torque3D operator *(T scalar, Torque3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static Torque3D operator /(Torque3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static Torque3D operator /(Torque3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static Torque3D operator -(Torque3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Translation3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Translation3D.g.cs index e8d4a197..a6bd9f74 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Translation3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Translation3D.g.cs @@ -138,11 +138,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.ILengthUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -162,8 +159,7 @@ public T Distance(Translation3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -176,9 +172,15 @@ public T DistanceSquared(Translation3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Translation3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -195,7 +197,8 @@ public Translation3D Normalize() public static Translation3D operator *(T scalar, Translation3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static Translation3D operator /(Translation3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static Translation3D operator /(Translation3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static Translation3D operator -(Translation3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Velocity1D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Velocity1D.g.cs index 6125ef8b..97fb893f 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Velocity1D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Velocity1D.g.cs @@ -163,6 +163,6 @@ namespace ktsu.Semantics.Quantities; /// Divides Velocity1D by Duration to produce Acceleration1D. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Acceleration1D operator /(Velocity1D left, Duration right) => Acceleration1D.Create(left.Quantity / right.Quantity); + public static Acceleration1D operator /(Velocity1D left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Acceleration1D.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Velocity2D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Velocity2D.g.cs index 8356e7b3..9294216c 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Velocity2D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Velocity2D.g.cs @@ -84,11 +84,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y) In(global::ktsu.Semantics.Quantities.IVelocityUnit unit) => (unit.FromBase(X), unit.FromBase(Y)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y); @@ -101,8 +98,7 @@ public T Distance(Velocity2D other) { T dX = X - other.X; T dY = Y - other.Y; - T sum = (dX * dX) + (dY * dY); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY); } /// Calculates the squared distance between two vectors. @@ -114,9 +110,15 @@ public T DistanceSquared(Velocity2D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Velocity2D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len }; } @@ -133,7 +135,8 @@ public Velocity2D Normalize() public static Velocity2D operator *(T scalar, Velocity2D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y }; /// Divides a vector by a scalar. - public static Velocity2D operator /(Velocity2D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar }; + /// is zero. + public static Velocity2D operator /(Velocity2D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar }; /// Negates a vector. public static Velocity2D operator -(Velocity2D vector) => new() { X = -vector.X, Y = -vector.Y }; @@ -141,6 +144,6 @@ public Velocity2D Normalize() public static Displacement2D operator *(Velocity2D left, Duration right) => new() { X = left.X * right.Value, Y = left.Y * right.Value }; /// Velocity2D / Duration = Acceleration2D. - public static Acceleration2D operator /(Velocity2D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value }; + public static Acceleration2D operator /(Velocity2D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value }; }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Velocity3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Velocity3D.g.cs index ab87d055..2e91f072 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Velocity3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Velocity3D.g.cs @@ -96,11 +96,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.IVelocityUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -120,8 +117,7 @@ public T Distance(Velocity3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -134,9 +130,15 @@ public T DistanceSquared(Velocity3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Velocity3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -153,7 +155,8 @@ public Velocity3D Normalize() public static Velocity3D operator *(T scalar, Velocity3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static Velocity3D operator /(Velocity3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static Velocity3D operator /(Velocity3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static Velocity3D operator -(Velocity3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; @@ -161,6 +164,6 @@ public Velocity3D Normalize() public static Displacement3D operator *(Velocity3D left, Duration right) => new() { X = left.X * right.Value, Y = left.Y * right.Value, Z = left.Z * right.Value }; /// Velocity3D / Duration = Acceleration3D. - public static Acceleration3D operator /(Velocity3D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value }; + public static Acceleration3D operator /(Velocity3D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value }; }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Velocity4D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Velocity4D.g.cs index a7834265..5bb6aee1 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Velocity4D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Velocity4D.g.cs @@ -108,11 +108,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z, T W) In(global::ktsu.Semantics.Quantities.IVelocityUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z), unit.FromBase(W)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z) + (W * W); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z, W); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z) + (W * W); @@ -127,8 +124,7 @@ public T Distance(Velocity4D other) T dY = Y - other.Y; T dZ = Z - other.Z; T dW = W - other.W; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ) + (dW * dW); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ, dW); } /// Calculates the squared distance between two vectors. @@ -142,9 +138,15 @@ public T DistanceSquared(Velocity4D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public Velocity4D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len, W = W / len }; } @@ -161,7 +163,8 @@ public Velocity4D Normalize() public static Velocity4D operator *(T scalar, Velocity4D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z, W = scalar * vector.W }; /// Divides a vector by a scalar. - public static Velocity4D operator /(Velocity4D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar, W = vector.W / scalar }; + /// is zero. + public static Velocity4D operator /(Velocity4D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar, W = vector.W / scalar }; /// Negates a vector. public static Velocity4D operator -(Velocity4D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z, W = -vector.W }; @@ -169,6 +172,6 @@ public Velocity4D Normalize() public static Displacement4D operator *(Velocity4D left, Duration right) => new() { X = left.X * right.Value, Y = left.Y * right.Value, Z = left.Z * right.Value, W = left.W * right.Value }; /// Velocity4D / Duration = Acceleration4D. - public static Acceleration4D operator /(Velocity4D left, Duration right) => new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value, W = left.W / right.Value }; + public static Acceleration4D operator /(Velocity4D left, Duration right) => T.IsZero(right.Value) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = left.X / right.Value, Y = left.Y / right.Value, Z = left.Z / right.Value, W = left.W / right.Value }; }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Voltage.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Voltage.g.cs index 57c598b8..8ccbda33 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Voltage.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Voltage.g.cs @@ -129,12 +129,12 @@ namespace ktsu.Semantics.Quantities; /// Divides Voltage by Resistance to produce Current1D. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Current1D operator /(Voltage left, Resistance right) => Current1D.Create(left.Quantity / right.Quantity); + public static Current1D operator /(Voltage left, Resistance right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Current1D.Create(left.Quantity / right.Quantity); /// /// Divides Voltage by Length to produce ElectricField1D. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static ElectricField1D operator /(Voltage left, Length right) => ElectricField1D.Create(left.Quantity / right.Quantity); + public static ElectricField1D operator /(Voltage left, Length right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : ElectricField1D.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/VoltageMagnitude.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/VoltageMagnitude.g.cs index 45349ab3..d99ca74f 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/VoltageMagnitude.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/VoltageMagnitude.g.cs @@ -124,13 +124,13 @@ namespace ktsu.Semantics.Quantities; /// Divides VoltageMagnitude by Resistance to produce CurrentMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static CurrentMagnitude operator /(VoltageMagnitude left, Resistance right) => CurrentMagnitude.Create(left.Quantity / right.Quantity); + public static CurrentMagnitude operator /(VoltageMagnitude left, Resistance right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : CurrentMagnitude.Create(left.Quantity / right.Quantity); /// /// Divides VoltageMagnitude by CurrentMagnitude to produce Resistance. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Resistance operator /(VoltageMagnitude left, CurrentMagnitude right) => Resistance.Create(left.Quantity / right.Quantity); + public static Resistance operator /(VoltageMagnitude left, CurrentMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Resistance.Create(left.Quantity / right.Quantity); /// /// Multiplies VoltageMagnitude by CurrentMagnitude to produce Power. @@ -142,13 +142,13 @@ namespace ktsu.Semantics.Quantities; /// Divides VoltageMagnitude by Length to produce ElectricFieldMagnitude. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static ElectricFieldMagnitude operator /(VoltageMagnitude left, Length right) => ElectricFieldMagnitude.Create(left.Quantity / right.Quantity); + public static ElectricFieldMagnitude operator /(VoltageMagnitude left, Length right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : ElectricFieldMagnitude.Create(left.Quantity / right.Quantity); /// /// Divides VoltageMagnitude by ElectricFieldMagnitude to produce Length. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Length operator /(VoltageMagnitude left, ElectricFieldMagnitude right) => Length.Create(left.Quantity / right.Quantity); + public static Length operator /(VoltageMagnitude left, ElectricFieldMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Length.Create(left.Quantity / right.Quantity); /// /// Multiplies VoltageMagnitude by Capacitance to produce ChargeMagnitude. @@ -172,12 +172,12 @@ namespace ktsu.Semantics.Quantities; /// Divides VoltageMagnitude by Pressure to produce Sensitivity. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Sensitivity operator /(VoltageMagnitude left, Pressure right) => Sensitivity.Create(left.Quantity / right.Quantity); + public static Sensitivity operator /(VoltageMagnitude left, Pressure right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Sensitivity.Create(left.Quantity / right.Quantity); /// /// Divides VoltageMagnitude by Sensitivity to produce Pressure. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Pressure operator /(VoltageMagnitude left, Sensitivity right) => Pressure.Create(left.Quantity / right.Quantity); + public static Pressure operator /(VoltageMagnitude left, Sensitivity right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Pressure.Create(left.Quantity / right.Quantity); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Volume.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Volume.g.cs index 798bc33e..2be59b6b 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Volume.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Volume.g.cs @@ -196,13 +196,13 @@ namespace ktsu.Semantics.Quantities; /// Divides Volume by Length to produce Area. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Area operator /(Volume left, Length right) => Area.Create(left.Quantity / right.Quantity); + public static Area operator /(Volume left, Length right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Area.Create(left.Quantity / right.Quantity); /// /// Divides Volume by Area to produce Length. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Length operator /(Volume left, Area right) => Length.Create(left.Quantity / right.Quantity); + public static Length operator /(Volume left, Area right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Length.Create(left.Quantity / right.Quantity); /// /// Multiplies Volume by Pressure to produce Energy. @@ -226,13 +226,13 @@ namespace ktsu.Semantics.Quantities; /// Divides Volume by Duration to produce VolumetricFlowRate. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static VolumetricFlowRate operator /(Volume left, Duration right) => VolumetricFlowRate.Create(left.Quantity / right.Quantity); + public static VolumetricFlowRate operator /(Volume left, Duration right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : VolumetricFlowRate.Create(left.Quantity / right.Quantity); /// /// Divides Volume by VolumetricFlowRate to produce Duration. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Duration operator /(Volume left, VolumetricFlowRate right) => Duration.Create(left.Quantity / right.Quantity); + public static Duration operator /(Volume left, VolumetricFlowRate right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Duration.Create(left.Quantity / right.Quantity); /// /// Multiplies Volume by ElectricPowerDensity to produce Power. diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Wavelength.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Wavelength.g.cs index 6227d84f..d2b90995 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Wavelength.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Wavelength.g.cs @@ -54,17 +54,17 @@ namespace ktsu.Semantics.Quantities; [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Wavelength operator +(Wavelength left, Wavelength right) => Create(left.Quantity + right.Quantity); - /// Scales a by a bare number. Throws when the number is negative. + /// Scales a by a bare number. Throws when the result is not positive. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Wavelength operator *(Wavelength left, T right) => Create(Vector0Guards.EnsureNonNegative(left.Quantity * right, nameof(right))); + public static Wavelength operator *(Wavelength left, T right) => Create(Vector0Guards.EnsurePositive(left.Quantity * right, nameof(right))); - /// Scales a by a bare number. Throws when the number is negative. + /// Scales a by a bare number. Throws when the result is not positive. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Wavelength operator *(T left, Wavelength right) => Create(Vector0Guards.EnsureNonNegative(left * right.Quantity, nameof(left))); + public static Wavelength operator *(T left, Wavelength right) => Create(Vector0Guards.EnsurePositive(left * right.Quantity, nameof(left))); - /// Divides a by a bare number. Throws when the number is negative. + /// Divides a by a bare number. Throws when the result is not positive. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Wavelength operator /(Wavelength left, T right) => T.IsZero(right) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Create(Vector0Guards.EnsureNonNegative(left.Quantity / right, nameof(right))); + public static Wavelength operator /(Wavelength left, T right) => T.IsZero(right) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Create(Vector0Guards.EnsurePositive(left.Quantity / right, nameof(right))); /// Divides one by another, giving the bare ratio. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] @@ -197,14 +197,14 @@ namespace ktsu.Semantics.Quantities; /// Implicit conversion to Length. public static implicit operator Length(Wavelength value) => Length.Create(value.Value); - /// Explicit conversion from Length. - public static explicit operator Wavelength(Length value) => Create(value.Value); + /// Explicit conversion from Length. Throws when the value is zero, which a Wavelength cannot be. + public static explicit operator Wavelength(Length value) => Create(Vector0Guards.EnsurePositive(value.Value, nameof(value))); - /// Creates a Wavelength from a Length value. - public static Wavelength From(Length value) => Create(value.Value); + /// Creates a Wavelength from a Length value. Throws when the value is zero, which a Wavelength cannot be. + public static Wavelength From(Length value) => Create(Vector0Guards.EnsurePositive(value.Value, nameof(value))); - /// Subtracts two Wavelength values, returning the absolute difference as a non-negative Wavelength. + /// Subtracts two Wavelength values, returning the absolute difference as a positive Wavelength. Throws when the two are equal, since a Wavelength cannot be zero; widen to first for a difference that may be. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] - public static Wavelength operator -(Wavelength left, Wavelength right) => Create(T.Abs(left.Quantity - right.Quantity)); + public static Wavelength operator -(Wavelength left, Wavelength right) => Create(Vector0Guards.EnsurePositive(T.Abs(left.Quantity - right.Quantity), nameof(right))); } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WeightVector.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WeightVector.g.cs index 5d79f81c..400971b7 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WeightVector.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WeightVector.g.cs @@ -82,11 +82,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.IForceUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -106,8 +103,7 @@ public T Distance(WeightVector other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -120,9 +116,15 @@ public T DistanceSquared(WeightVector other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public WeightVector Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -139,7 +141,8 @@ public WeightVector Normalize() public static WeightVector operator *(T scalar, WeightVector vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static WeightVector operator /(WeightVector vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static WeightVector operator /(WeightVector vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static WeightVector operator -(WeightVector vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WindVelocity3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WindVelocity3D.g.cs index c78fd59e..47ad968b 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WindVelocity3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WindVelocity3D.g.cs @@ -96,11 +96,8 @@ namespace ktsu.Semantics.Quantities; public (T X, T Y, T Z) In(global::ktsu.Semantics.Quantities.IVelocityUnit unit) => (unit.FromBase(X), unit.FromBase(Y), unit.FromBase(Z)); /// Calculates the length of the vector. - public T Length() - { - T sum = (X * X) + (Y * Y) + (Z * Z); - return StorageMath.Sqrt(sum); - } + /// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range. + public T Length() => StorageMath.Hypot(X, Y, Z); /// Calculates the squared length of the vector. public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z); @@ -120,8 +117,7 @@ public T Distance(WindVelocity3D other) T dX = X - other.X; T dY = Y - other.Y; T dZ = Z - other.Z; - T sum = (dX * dX) + (dY * dY) + (dZ * dZ); - return StorageMath.Sqrt(sum); + return StorageMath.Hypot(dX, dY, dZ); } /// Calculates the squared distance between two vectors. @@ -134,9 +130,15 @@ public T DistanceSquared(WindVelocity3D other) } /// Returns a normalized version of the vector. + /// The vector has zero length, so it has no direction. public WindVelocity3D Normalize() { T len = Length(); + if (T.IsZero(len)) + { + throw new System.DivideByZeroException("Cannot normalize a zero-length vector."); + } + return new() { X = X / len, Y = Y / len, Z = Z / len }; } @@ -153,7 +155,8 @@ public WindVelocity3D Normalize() public static WindVelocity3D operator *(T scalar, WindVelocity3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z }; /// Divides a vector by a scalar. - public static WindVelocity3D operator /(WindVelocity3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; + /// is zero. + public static WindVelocity3D operator /(WindVelocity3D vector, T scalar) => T.IsZero(scalar) ? throw new System.DivideByZeroException("Cannot divide by zero.") : new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar }; /// Negates a vector. public static WindVelocity3D operator -(WindVelocity3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; diff --git a/Semantics.Quantities/LogarithmicStorage.cs b/Semantics.Quantities/LogarithmicStorage.cs new file mode 100644 index 00000000..5bcb9763 --- /dev/null +++ b/Semantics.Quantities/LogarithmicStorage.cs @@ -0,0 +1,85 @@ +// Copyright (c) 2023-2026 ktsu-dev contributors + +namespace ktsu.Semantics.Quantities; + +using System; +using System.Globalization; +using System.Numerics; + +/// +/// Brings the result of a logarithmic-scale conversion into the storage type, with one +/// documented failure for a result the storage type cannot hold. +/// +/// +/// A linear value of zero is a level of negative infinity. and hold +/// that; , the integer types and most others do not, and T.CreateChecked reported it +/// as a bare that contradicted the conversion's own documentation. The same +/// happens converting back from a level so high its linear value is past the type's range. +/// +internal static class LogarithmicStorage +{ + /// Converts the level computed from a linear value. + /// The numeric storage type. + /// The level, which is negative infinity for a linear value of zero. + /// The name of the parameter holding the linear value. + /// The level in . + /// + /// cannot hold the level: the linear value is zero, or negative, or so near zero + /// that its level is past the type's range. + /// + internal static T FromLinear(double level, string paramName) + where T : struct, INumber + { + if (TryConvert(level, out T result)) + { + return result; + } + + throw new ArgumentOutOfRangeException(paramName, string.Format( + CultureInfo.InvariantCulture, + "The level of this value is {0}, which {1} cannot hold. A linear value of zero is negative infinity on every logarithmic scale.", + level, + typeof(T).Name)); + } + + /// Converts the linear value computed from a level. + /// The numeric storage type. + /// The linear value. + /// The linear value in . + /// The level is so high that cannot hold its linear value. + internal static T ToLinear(double linear) + where T : struct, INumber + { + if (TryConvert(linear, out T result)) + { + return result; + } + + throw new OverflowException(string.Format( + CultureInfo.InvariantCulture, + "The linear value of this level is {0}, which {1} cannot hold.", + linear, + typeof(T).Name)); + } + + private static bool TryConvert(double value, out T result) + where T : struct, INumber + { + if (double.IsNaN(value)) + { + result = default; + return false; + } + + try + { + result = T.CreateChecked(value); + return true; + } + catch (OverflowException) + { + result = default; + return false; + } + } +} diff --git a/Semantics.Quantities/StorageLiteral.cs b/Semantics.Quantities/StorageLiteral.cs index 56326949..4026a84e 100644 --- a/Semantics.Quantities/StorageLiteral.cs +++ b/Semantics.Quantities/StorageLiteral.cs @@ -80,6 +80,69 @@ internal static class StorageLiteral } } + /// + /// Materialises a physical constant's literal into , for the generated + /// PhysicalConstants accessors, which call it once per constant and closed generic type. + /// + /// The numeric storage type. + /// The literal as written in the metadata. + /// The constant's name, for the exception message. + /// The constant in . + /// The constant is too large for . + /// + /// holds the constant with less than about six significant digits: an integer type + /// truncating 9.80665 to 9, or rounding 6.62607015e-34 to zero. + /// + /// + /// Each constant is materialised on its own, so a constant cannot hold fails alone + /// rather than taking every other constant of its domain with it, which is what one shared static + /// initializer did. Integer types are allowed every constant that is a whole number in range, such as the + /// speed of light in a . + /// + internal static T Constant(string literal, string name) + where T : struct, INumber + { + double expected = double.Parse(literal, NumberStyles.Float, CultureInfo.InvariantCulture); + T value = TryParseLiteral(literal, out T parsed) ? parsed : T.CreateChecked(expected); + + if (expected != 0.0 && !KeepsPrecision(value, expected)) + { + throw new ArithmeticException(string.Format( + CultureInfo.InvariantCulture, + "{0} ({1}) cannot be represented in {2} without losing its precision; it would read as {3}.", + name, + literal, + typeof(T).Name, + value)); + } + + return value; + } + + /// + /// Reports whether a materialised constant agrees with its value to a relative 1e-6. + /// + /// The numeric storage type. + /// The constant in . + /// The constant as a . + /// unless the value lost precision a would keep. + private static bool KeepsPrecision(T value, double expected) + where T : struct, INumber + { + double actual; + try + { + actual = double.CreateChecked(value); + } + catch (NotSupportedException) + { + // A type that cannot say what it holds as a double is trusted, as its parse was. + return true; + } + + return Math.Abs(actual - expected) <= Math.Abs(expected) * 1e-6; + } + /// /// Parses a literal with , treating a parse that throws for that style /// the same as one that returns . diff --git a/Semantics.Quantities/StorageMath.cs b/Semantics.Quantities/StorageMath.cs index 7bc86b11..13c37cce 100644 --- a/Semantics.Quantities/StorageMath.cs +++ b/Semantics.Quantities/StorageMath.cs @@ -281,6 +281,82 @@ public static T Hypot(T x, T y) return larger * Sqrt(T.One + (ratio * ratio)); } + /// + /// The length of a three-component vector, scaled the way is so components + /// whose squares leave the range of still have their length (#327). + /// + /// The numeric storage type. + /// The first component. + /// The second component. + /// The third component. + /// The square root of x² + y² + z², or its floor for an integer type. + internal static T Hypot(T x, T y, T z) + where T : struct, INumber + { + if (IsRoundedThroughDouble()) + { + double dx = double.CreateChecked(x); + double dy = double.CreateChecked(y); + double dz = double.CreateChecked(z); + return T.CreateChecked(double.Hypot(double.Hypot(dx, dy), dz)); + } + + T larger = T.Max(T.Abs(x), T.Max(T.Abs(y), T.Abs(z))); + if (T.IsZero(larger)) + { + return T.Zero; + } + + if (HasFloorDivision()) + { + return Sqrt((x * x) + (y * y) + (z * z)); + } + + T rx = x / larger; + T ry = y / larger; + T rz = z / larger; + return larger * Sqrt((rx * rx) + (ry * ry) + (rz * rz)); + } + + /// + /// The length of a four-component vector, scaled as is. + /// + /// The numeric storage type. + /// The first component. + /// The second component. + /// The third component. + /// The fourth component. + /// The square root of x² + y² + z² + w², or its floor for an integer type. + internal static T Hypot(T x, T y, T z, T w) + where T : struct, INumber + { + if (IsRoundedThroughDouble()) + { + double dx = double.CreateChecked(x); + double dy = double.CreateChecked(y); + double dz = double.CreateChecked(z); + double dw = double.CreateChecked(w); + return T.CreateChecked(double.Hypot(double.Hypot(dx, dy), double.Hypot(dz, dw))); + } + + T larger = T.Max(T.Max(T.Abs(x), T.Abs(y)), T.Max(T.Abs(z), T.Abs(w))); + if (T.IsZero(larger)) + { + return T.Zero; + } + + if (HasFloorDivision()) + { + return Sqrt((x * x) + (y * y) + (z * z) + (w * w)); + } + + T rx = x / larger; + T ry = y / larger; + T rz = z / larger; + T rw = w / larger; + return larger * Sqrt((rx * rx) + (ry * ry) + (rz * rz) + (rw * rw)); + } + /// /// Reports whether is one of the primitives whose square root has always /// been taken through . @@ -593,8 +669,19 @@ private static T RootByDescent(T value, int degree, T two) /// The root, to the precision the type holds. /// The estimate does not settle within steps. /// + /// /// On the same terms as : an estimate that stops changing is the root, and /// one alternating between two neighbours is rounding, so the smaller of the two is taken. + /// + /// + /// A type with no fixed precision, such as PreciseNumber, never does either: its products keep + /// every digit, so each estimate is about twice as long as the last and never repeats, and a step + /// cost four times the one before until the thread hung (#457). Such a type stops once a step moves + /// the estimate by less than one part in 10^60, which Newton's quadratic convergence reaches from the + /// seed in about three steps. A fixed-precision type cannot hold that tolerance + /// (it is zero in ), so it settles exactly as before. A step no smaller than the + /// one before it has stopped converging too, and the estimate is returned there. + /// /// private static T RootBySettling(T value, int degree, T two) where T : struct, INumber @@ -603,6 +690,8 @@ private static T RootBySettling(T value, int degree, T two) T countLessOne = count - T.One; T estimate = SeedForRoot(value, degree, two); T previous = estimate; + T? lastStep = null; + T tolerance = RelativeTolerance(); for (int iteration = 0; iteration < MaximumIterations; iteration++) { @@ -626,6 +715,19 @@ private static T RootBySettling(T value, int degree, T two) return T.Min(estimate, next); } + T step = T.Abs(next - estimate); + if (step <= T.Abs(next) * tolerance) + { + return next; + } + + // A step no smaller than the last one has stopped converging: what is left is rounding. + if (lastStep is T last && step >= last) + { + return estimate; + } + + lastStep = step; previous = estimate; estimate = next; } @@ -633,6 +735,28 @@ private static T RootBySettling(T value, int degree, T two) throw new ArithmeticException($"The root of degree {degree} did not settle within {MaximumIterations} Newton steps."); } + /// + /// The relative step below which stops for a type that never settles. + /// + /// The numeric storage type. + /// 10^-60 in , or zero where the type cannot hold it. + private static T RelativeTolerance() + where T : struct, INumber + { + try + { + return T.CreateChecked(1e-60); + } + catch (NotSupportedException) + { + return T.Zero; + } + catch (OverflowException) + { + return T.Zero; + } + } + /// /// Chooses the first Newton estimate for the th root of a positive value. /// diff --git a/Semantics.SourceGenerators/Generators/LogarithmicScalesGenerator.cs b/Semantics.SourceGenerators/Generators/LogarithmicScalesGenerator.cs index dfdef786..55931af7 100644 --- a/Semantics.SourceGenerators/Generators/LogarithmicScalesGenerator.cs +++ b/Semantics.SourceGenerators/Generators/LogarithmicScalesGenerator.cs @@ -175,8 +175,9 @@ private static void WriteConversion(CodeBlocker cb, LogarithmicScaleDefinition s cb.WriteLine($"/// {conversion.FromSummary ?? $"Creates a value from the linear {linear}."}"); cb.WriteLine(Emit.SummaryClose); cb.WriteLine($"/// The linear ."); - cb.WriteLine($"/// A new . A linear value of zero maps to negative infinity."); + cb.WriteLine($"/// A new . A linear value of zero maps to negative infinity where can hold it."); WriteDoublePrecisionRemarks(cb); + cb.WriteLine("/// cannot hold the result, as for a linear value of zero with or integer storage."); cb.WriteLine($"public static {fullType} {fromName}({linear} linear)"); using (new Scope(cb)) { @@ -186,7 +187,7 @@ private static void WriteConversion(CodeBlocker cb, LogarithmicScaleDefinition s cb.WriteLine($"double reference = {referenceExpr};"); } - cb.WriteLine($"return new(T.CreateChecked({multiplier} * {logExpr}));"); + cb.WriteLine($"return new(LogarithmicStorage.FromLinear({multiplier} * {logExpr}, nameof(linear)));"); } cb.NewLine(); @@ -201,6 +202,7 @@ private static void WriteConversion(CodeBlocker cb, LogarithmicScaleDefinition s cb.WriteLine(Emit.SummaryClose); cb.WriteLine($"/// The linear ."); WriteDoublePrecisionRemarks(cb); + cb.WriteLine("/// cannot hold the linear value of a level this high."); cb.WriteLine($"public {linear} {toName}()"); using (new Scope(cb)) { @@ -210,7 +212,7 @@ private static void WriteConversion(CodeBlocker cb, LogarithmicScaleDefinition s cb.WriteLine($"double reference = {referenceExpr};"); } - cb.WriteLine($"return {linear}.Create(T.CreateChecked({inverseExpr}));"); + cb.WriteLine($"return {linear}.Create(LogarithmicStorage.ToLinear({inverseExpr}));"); } cb.NewLine(); diff --git a/Semantics.SourceGenerators/Generators/PhysicalConstantsGenerator.cs b/Semantics.SourceGenerators/Generators/PhysicalConstantsGenerator.cs index 6141b865..1bb33f81 100644 --- a/Semantics.SourceGenerators/Generators/PhysicalConstantsGenerator.cs +++ b/Semantics.SourceGenerators/Generators/PhysicalConstantsGenerator.cs @@ -26,8 +26,8 @@ public class PhysicalConstantsGenerator : SemanticsGenerator { /// /// Name of the private nested holder that caches the parsed value of each constant per closed - /// generic type. A static field on a generic type is initialised once per T, so callers - /// pay the parse exactly once regardless of how hot the accessor is. + /// generic type. A static field on a generic type exists once per T, so callers pay the + /// parse once per constant regardless of how hot the accessor is. /// private const string HolderName = "Values"; @@ -37,12 +37,10 @@ public class PhysicalConstantsGenerator : SemanticsGenerator private const string NumericConstraint = "where T : struct, INumber"; /// - /// Styles accepted when parsing a constant literal. - /// covers the exponent forms used in the metadata (for example 6.62607015e-34); the default - /// Parse(string, IFormatProvider) overload resolves to NumberStyles.Number for some - /// numeric types, which rejects an exponent, so the style is always passed explicitly. + /// Prefix of the private field caching each constant once it has been materialised. Each constant is + /// materialised on its own, through StorageLiteral.Constant, when it is first read. /// - private const string ParseStyles = "NumberStyles.Float"; + private const string CachePrefix = "cached"; public PhysicalConstantsGenerator() : base("domains.json") { } @@ -60,7 +58,6 @@ protected override void Generate(SourceProductionContext context, DomainsMetadat Namespace = "ktsu.Semantics.Quantities", Usings = { - "System.Globalization", "System.Numerics", }, }; @@ -125,12 +122,20 @@ protected override void Generate(SourceProductionContext context, DomainsMetadat BodyFactory = (body) => body.Write($" {NumericConstraint} => {HolderName}.{constant.Name};"), }); + // One lazily filled field per constant, so a constant T cannot hold throws from its own accessor + // rather than failing the shared static initializer for every constant of the domain. holderClass.Members.Add(new FieldTemplate() { Comments = {$"/// {constant.Description}"}, - Keywords = {Emit.Internal, Emit.Static, "readonly", "T"}, - Name = constant.Name, - DefaultValue = $"T.Parse(\"{constant.Value}\", {ParseStyles}, CultureInfo.InvariantCulture)", + Keywords = {Emit.Internal, Emit.Static, "T"}, + Name = $"{constant.Name} => {CachePrefix}{constant.Name} ??= StorageLiteral.Constant(\"{constant.Value}\", \"{constant.Name}\")", + }); + + holderClass.Members.Add(new FieldTemplate() + { + Comments = {$"/// {constant.Name} once materialised into ."}, + Keywords = {"private", Emit.Static, "T?"}, + Name = $"{CachePrefix}{constant.Name}", }); } diff --git a/Semantics.SourceGenerators/Generators/QuantitiesGenerator.cs b/Semantics.SourceGenerators/Generators/QuantitiesGenerator.cs index 0590f630..07792cd5 100644 --- a/Semantics.SourceGenerators/Generators/QuantitiesGenerator.cs +++ b/Semantics.SourceGenerators/Generators/QuantitiesGenerator.cs @@ -783,7 +783,7 @@ private static void AddDimensionAndInMembers( /// T.Abs(left - right), per the locked decision in #52 — so the plain one is skipped /// rather than emitted twice. /// - private static void AddValueTypeCore(ClassTemplate cls, string fullType, bool isV0) + private static void AddValueTypeCore(ClassTemplate cls, string fullType, bool isV0, bool strictPositive = false) { // A doc comment is XML, so the type argument is spelled with braces: Mass{T}, not Mass. string docRef = $"', '}')}\"/>"; @@ -888,10 +888,17 @@ private static void AddValueTypeCore(ClassTemplate cls, string fullType, bool is }); } - string scaledLeft = isV0 ? "Create(Vector0Guards.EnsureNonNegative(left.Quantity * right, nameof(right)))" : "Create(left.Quantity * right)"; - string scaledRight = isV0 ? "Create(Vector0Guards.EnsureNonNegative(left * right.Quantity, nameof(left)))" : "Create(left * right.Quantity)"; - string divided = isV0 ? "Create(Vector0Guards.EnsureNonNegative(left.Quantity / right, nameof(right)))" : "Create(left.Quantity / right)"; - string scaleRemark = isV0 ? " Throws when the number is negative." : string.Empty; + // A strictly positive overload (#51) keeps its stricter rule through scaling too (#354), so + // w * 0 and w / infinity cannot produce the zero its factories refuse. + string guard = strictPositive ? "EnsurePositive" : "EnsureNonNegative"; + string scaledLeft = isV0 ? $"Create(Vector0Guards.{guard}(left.Quantity * right, nameof(right)))" : "Create(left.Quantity * right)"; + string scaledRight = isV0 ? $"Create(Vector0Guards.{guard}(left * right.Quantity, nameof(left)))" : "Create(left * right.Quantity)"; + string divided = isV0 ? $"Create(Vector0Guards.{guard}(left.Quantity / right, nameof(right)))" : "Create(left.Quantity / right)"; + string scaleRemark = !isV0 + ? string.Empty + : strictPositive + ? " Throws when the result is not positive." + : " Throws when the number is negative."; AddBinaryOperator(cls, fullType, "*", fullType, "T", $"=> {scaledLeft};", $"Scales a {docRef} by a bare number.{scaleRemark}"); @@ -1279,8 +1286,10 @@ private void EmitOverloadType( Constraints = {"where T : struct, INumber"}, }; + bool strictPositive = type.Magnitude == Magnitude.Positive; + // Everything a quantity used to inherit from the PhysicalQuantity record. - AddValueTypeCore(cls, fullType, isV0: vectorForm == 0); + AddValueTypeCore(cls, fullType, isV0: vectorForm == 0, strictPositive: strictPositive); // Zero property cls.Members.Add(new FieldTemplate() @@ -1296,7 +1305,6 @@ private void EmitOverloadType( // dimensions.json (#51, e.g. Wavelength, Period, HalfLife) get the stricter // EnsurePositive guard so a zero input is rejected too. V1 overloads accept // any sign, and like their V1 base hold a difference, so they leave out the unit offset (#283). - bool strictPositive = type.Magnitude == Magnitude.Positive; AddUnitFactories( cls, dim.AvailableUnits, @@ -1319,35 +1327,48 @@ private void EmitOverloadType( BodyFactory = (body) => body.Write($"=> {baseFullType}.Create(value.Value);"), }); + // Narrowing takes the overload's own rule with it: a strictly positive overload refuses a zero + // base (#354). The base already guarantees anything weaker. + string narrowed = strictPositive ? "Create(Vector0Guards.EnsurePositive(value.Value, nameof(value)))" : "Create(value.Value)"; + string narrowRemark = strictPositive ? $" Throws when the value is zero, which a {typeName} cannot be." : string.Empty; + // Explicit narrowing from base type cls.Members.Add(new MethodTemplate() { - Comments = {$"/// Explicit conversion from {baseTypeName}."}, + Comments = {$"/// Explicit conversion from {baseTypeName}.{narrowRemark}"}, Keywords = {Emit.Public, Emit.Static, "explicit", "operator"}, Name = fullType, Parameters = {new ParameterTemplate { Type = baseFullType, Name = Emit.ValueParameter }}, - BodyFactory = (body) => body.Write($"=> Create(value.Value);"), + BodyFactory = (body) => body.Write($"=> {narrowed};"), }); // Factory-style narrowing from base cls.Members.Add(new MethodTemplate() { - Comments = {$"/// Creates a {typeName} from a {baseTypeName} value."}, + Comments = {$"/// Creates a {typeName} from a {baseTypeName} value.{narrowRemark}"}, Keywords = {Emit.Public, Emit.Static, fullType}, Name = "From", Parameters = {new ParameterTemplate { Type = baseFullType, Name = Emit.ValueParameter }}, - BodyFactory = (body) => body.Write("=> Create(value.Value);"), + BodyFactory = (body) => body.Write($"=> {narrowed};"), }); // V0 overload subtraction returns the same V0 of T.Abs(left - right) (locked // in #52). The overload-typed operator hides the base PhysicalQuantity's plain // subtraction so overloads stay in their own type and the magnitude invariant // is preserved. + // For a strictly positive overload the difference of two equal values is zero, which the type + // cannot hold, so it throws like every other path to zero (#354). if (vectorForm == 0) { + string difference = strictPositive + ? "=> Create(Vector0Guards.EnsurePositive(T.Abs(left.Quantity - right.Quantity), nameof(right)));" + : "=> Create(T.Abs(left.Quantity - right.Quantity));"; + string differenceSummary = strictPositive + ? $"/// Subtracts two {typeName} values, returning the absolute difference as a positive {typeName}. Throws when the two are equal, since a {typeName} cannot be zero; widen to first for a difference that may be." + : $"/// Subtracts two {typeName} values, returning the absolute difference as a non-negative {typeName}."; cls.Members.Add(new MethodTemplate() { - Comments = {$"/// Subtracts two {typeName} values, returning the absolute difference as a non-negative {typeName}."}, + Comments = {differenceSummary}, Attributes = {Emit.PhysicsOperatorSuppression}, Keywords = {Emit.Public, Emit.Static, fullType}, Name = "operator -", @@ -1356,7 +1377,7 @@ private void EmitOverloadType( new ParameterTemplate { Type = fullType, Name = "left" }, new ParameterTemplate { Type = fullType, Name = Emit.RightParameter }, }, - BodyFactory = (body) => body.Write("=> Create(T.Abs(left.Quantity - right.Quantity));"), + BodyFactory = (body) => body.Write(difference), }); } @@ -1504,8 +1525,9 @@ private static void EmitScalarOperators(ClassTemplate cls, string ownerTypeName, new ParameterTemplate { Type = $"{op.LeftTypeName}", Name = "left" }, new ParameterTemplate { Type = $"{op.RightTypeName}", Name = Emit.RightParameter }, }, - BodyFactory = (body) => body.Write( - $"=> {op.ReturnTypeName}.Create(left.Quantity {op.Op} right.Quantity);"), + BodyFactory = (body) => body.Write(op.Op == "/" + ? $"=> {DivideByZeroGuard("right.Quantity")}{op.ReturnTypeName}.Create(left.Quantity / right.Quantity);" + : $"=> {op.ReturnTypeName}.Create(left.Quantity {op.Op} right.Quantity);"), }); } else @@ -1542,7 +1564,8 @@ private static void EmitInlineCrossDimOp(ClassTemplate cls, OperatorInfo op, Emi { // VN op V0: component-wise with right.Value string initExpr = string.Join(", ", resultComponents.Select(c => $"{c} = left.{c} {op.Op} right.Value")); - bodyExpr = $"=> new() {{ {initExpr} }};"; + string guard = op.Op == "/" ? DivideByZeroGuard("right.Value") : string.Empty; + bodyExpr = $"=> {guard}new() {{ {initExpr} }};"; } else if (leftForm <= 1 && rightForm >= 2) { @@ -1608,8 +1631,9 @@ private static void EmitVectorCrossDimOperators(CodeBlocker cb, string ownerType { // VN * V0 or VN / V0 => VN result string initExpr = string.Join(", ", resultComponents.Select(c => $"{c} = left.{c} {op.Op} right.Value")); + string guard = op.Op == "/" ? DivideByZeroGuard("right.Value") : string.Empty; cb.WriteLine($"/// {op.LeftTypeName} {op.Op} {op.RightTypeName} = {op.ReturnTypeName}."); - cb.WriteLine($"public static {op.ReturnTypeName} operator {op.Op}({op.LeftTypeName} left, {op.RightTypeName} right) => new() {{ {initExpr} }};"); + cb.WriteLine($"public static {op.ReturnTypeName} operator {op.Op}({op.LeftTypeName} left, {op.RightTypeName} right) => {guard}new() {{ {initExpr} }};"); cb.NewLine(); } else if (leftForm <= 1 && rightForm >= 2 && op.Op == "*") @@ -1815,13 +1839,11 @@ private static void WriteVectorMethods(CodeBlocker cb, string fullType, string[] { string sumOfSquares = string.Join(" + ", components.Select(c => $"({c} * {c})")); + // The norm is scaled by the largest component rather than squared and summed, so a vector + // whose squares leave the storage type still has its length (#327). cb.WriteLine("/// Calculates the length of the vector."); - cb.WriteLine("public T Length()"); - using (new Scope(cb)) - { - cb.WriteLine($"T sum = {sumOfSquares};"); - cb.WriteLine("return StorageMath.Sqrt(sum);"); - } + cb.WriteLine("/// Computed without squaring the components outright, so a length the storage type can hold is returned even when the squares of the components are past its range."); + cb.WriteLine($"public T Length() => StorageMath.Hypot({string.Join(", ", components)});"); cb.NewLine(); @@ -1855,9 +1877,7 @@ private static void WriteVectorMethods(CodeBlocker cb, string fullType, string[] cb.WriteLine($"T d{comp} = {comp} - other.{comp};"); } - string distSum = string.Join(" + ", components.Select(c => $"(d{c} * d{c})")); - cb.WriteLine($"T sum = {distSum};"); - cb.WriteLine("return StorageMath.Sqrt(sum);"); + cb.WriteLine($"return StorageMath.Hypot({string.Join(", ", components.Select(c => $"d{c}"))});"); } cb.NewLine(); @@ -1878,10 +1898,18 @@ private static void WriteVectorMethods(CodeBlocker cb, string fullType, string[] cb.NewLine(); cb.WriteLine("/// Returns a normalized version of the vector."); + cb.WriteLine("/// The vector has zero length, so it has no direction."); cb.WriteLine($"public {fullType} Normalize()"); using (new Scope(cb)) { cb.WriteLine("T len = Length();"); + cb.WriteLine("if (T.IsZero(len))"); + using (new Scope(cb)) + { + cb.WriteLine("throw new System.DivideByZeroException(\"Cannot normalize a zero-length vector.\");"); + } + + cb.NewLine(); string normInit = string.Join(", ", components.Select(c => $"{c} = {c} / len")); cb.WriteLine($"return new() {{ {normInit} }};"); } @@ -1913,7 +1941,8 @@ private static void WriteVectorOperators(CodeBlocker cb, string fullType, string string divInit = string.Join(", ", components.Select(c => $"{c} = vector.{c} / scalar")); cb.WriteLine("/// Divides a vector by a scalar."); - cb.WriteLine($"public static {fullType} operator /({fullType} vector, T scalar) => new() {{ {divInit} }};"); + cb.WriteLine("/// is zero."); + cb.WriteLine($"public static {fullType} operator /({fullType} vector, T scalar) => {DivideByZeroGuard("scalar")}new() {{ {divInit} }};"); cb.NewLine(); string negInit = string.Join(", ", components.Select(c => $"{c} = -vector.{c}")); @@ -1925,6 +1954,16 @@ private static void WriteVectorOperators(CodeBlocker cb, string fullType, string #region Helper Methods + /// + /// The start of an expression body that throws when + /// is zero, the same way the same-dimension operators do (#480), so a + /// quotient never holds an infinity or a NaN that the factories would have refused. + /// + /// The expression divided by. + /// A conditional to put before the quotient. + private static string DivideByZeroGuard(string divisor) => + $"T.IsZero({divisor}) ? throw new System.DivideByZeroException(\"Cannot divide by zero.\") : "; + private static VectorFormDefinition? GetFormDef(PhysicalDimension dim, int form) => form switch { 0 => dim.Quantities.Vector0, diff --git a/Semantics.SourceGenerators/Metadata/domains.json b/Semantics.SourceGenerators/Metadata/domains.json index 84097a95..c3c4ade5 100644 --- a/Semantics.SourceGenerators/Metadata/domains.json +++ b/Semantics.SourceGenerators/Metadata/domains.json @@ -36,12 +36,12 @@ }, { "name": "PermittivityOfFreeSpace", - "description": "Electric permittivity of free space: 8.8541878128 × 10⁻¹² F/m (exact, derived)", + "description": "Electric permittivity of free space: 8.8541878128 × 10⁻¹² F/m (CODATA 2018; measured, not exact, since the 2019 SI redefinition)", "value": "8.8541878128e-12" }, { "name": "PermeabilityOfFreeSpace", - "description": "Magnetic permeability of free space: 4π × 10⁻⁷ H/m (exact by definition)", + "description": "Magnetic permeability of free space: 1.25663706212 × 10⁻⁶ H/m (CODATA 2018; close to but no longer exactly 4π × 10⁻⁷ since the 2019 SI redefinition)", "value": "1.25663706212e-6" }, { @@ -133,8 +133,8 @@ "constants": [ { "name": "AbsoluteZeroInCelsius", - "description": "Absolute zero in Celsius: 273.15 K (exact by definition)", - "value": "273.15" + "description": "Absolute zero in Celsius: −273.15 °C (exact by definition)", + "value": "-273.15" }, { "name": "WaterTriplePoint", @@ -223,12 +223,12 @@ { "name": "WaterIonProduct", "description": "Water ion product (Kw) at 25°C: 1.0 × 10⁻¹⁴ (pKw = 14.0)", - "value": "14.0" + "value": "1.0e-14" }, { "name": "MolarVolumeSTP", - "description": "Molar volume of ideal gas at STP: 22.413969545014137 L/mol (calculated from R*T/P at 273.15K, 101325Pa)", - "value": "22.413969545014137" + "description": "Molar volume of ideal gas at STP: 0.022413969545014137 m³/mol, or 22.413969545014137 L/mol (calculated from R*T/P at 273.15K, 101325Pa)", + "value": "0.022413969545014137" }, { "name": "Ln2", diff --git a/Semantics.Test/Quantities/PhysicsBugfixTests.cs b/Semantics.Test/Quantities/PhysicsBugfixTests.cs new file mode 100644 index 00000000..ee7cd741 --- /dev/null +++ b/Semantics.Test/Quantities/PhysicsBugfixTests.cs @@ -0,0 +1,135 @@ +// Copyright (c) 2023-2026 ktsu-dev contributors + +namespace ktsu.Semantics.Test.Quantities; + +using System; +using ktsu.Semantics.Quantities; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +/// +/// Constants that are right and survive their siblings (#386, #392), logarithmic conversions with no +/// infinity to land on (#352), strictly positive overloads that stay positive (#354), and division by zero +/// that throws on every generated path (#480). +/// +[TestClass] +public sealed class PhysicsBugfixTests +{ + [TestMethod] + public void AbsoluteZeroInCelsiusIsZeroKelvin() + { + double celsius = PhysicalConstants.Generic.AbsoluteZeroInCelsius(); + Assert.AreEqual(-273.15, celsius, 1e-12); + Assert.AreEqual(0.0, Temperature.FromCelsius(celsius).Value, 1e-9); + } + + [TestMethod] + public void WaterIonProductIsKw() + { + Assert.AreEqual(1e-14, PhysicalConstants.Generic.WaterIonProduct(), 1e-28); + } + + [TestMethod] + public void MolarVolumeStpIsInCubicMetresPerMole() + { + double expected = PhysicalConstants.Generic.GasConstant() * 273.15 / 101325.0; + Assert.AreEqual(expected, PhysicalConstants.Generic.MolarVolumeSTP(), 1e-12); + } + + [TestMethod] + public void IntegerStorageReadsTheConstantsItCanHold() + { + Assert.AreEqual(299792458L, PhysicalConstants.Fundamental.SpeedOfLight()); + Assert.AreEqual(101325, PhysicalConstants.ClassicalMechanics.StandardAtmosphericPressure()); + Assert.AreEqual(7, PH.Neutral.Value); + } + + [TestMethod] + public void AConstantTheStorageTypeCannotHoldFailsAlone() + { + Assert.ThrowsExactly(() => PhysicalConstants.Fundamental.AvogadroNumber()); + Assert.ThrowsExactly(() => PhysicalConstants.ClassicalMechanics.StandardGravity()); + Assert.AreEqual(299792458L, PhysicalConstants.Fundamental.SpeedOfLight()); + } + + [TestMethod] + public void DecimalRefusesAConstantItWouldRoundAway() + { + Assert.ThrowsExactly(() => PhysicalConstants.Fundamental.PlanckConstant()); + Assert.ThrowsExactly(() => PhysicalConstants.NuclearPhysics.AtomicMassUnit()); + Assert.AreEqual(299792458m, PhysicalConstants.Fundamental.SpeedOfLight()); + } + + [TestMethod] + public void ALinearZeroWithNoInfinityToHoldThrowsArgumentOutOfRange() + { + Assert.ThrowsExactly(() => Gain.Silence.ToDecibels()); + Assert.ThrowsExactly(() => Gain.Silence.ToDecibels()); + Assert.ThrowsExactly(() => SoundPressureLevel.FromSoundPressure(SoundPressure.Zero)); + Assert.ThrowsExactly(() => PH.FromHydrogenConcentration(Concentration.Zero)); + Assert.ThrowsExactly(() => Semitones.FromFrequencyRatio(Ratio.Zero)); + Assert.ThrowsExactly(() => Decibels.FromAmplitude(0m)); + Assert.ThrowsExactly(() => Decibels.FromPower(0m)); + } + + [TestMethod] + public void ALinearZeroIsNegativeInfinityWhereTheTypeHoldsIt() + { + Assert.AreEqual(double.NegativeInfinity, Gain.Silence.ToDecibels().Value); + Assert.AreEqual(float.NegativeInfinity, Gain.Silence.ToDecibels().Value); + } + + [TestMethod] + public void ALevelTooHighForTheLinearTypeThrowsOverflow() => + Assert.ThrowsExactly(() => Decibels.Create(600m).ToAmplitude()); + + [TestMethod] + public void StrictlyPositiveOverloadsDoNotReachZero() + { + Wavelength w = Wavelength.FromMeter(1); + Period p = Period.FromSecond(1); + HalfLife h = HalfLife.FromSecond(1); + + Assert.ThrowsExactly(() => w * 0.0); + Assert.ThrowsExactly(() => 0.0 * w); + Assert.ThrowsExactly(() => w - w); + Assert.ThrowsExactly(() => w / double.PositiveInfinity); + Assert.ThrowsExactly(() => Wavelength.From(Length.Zero)); + Assert.ThrowsExactly(() => (Wavelength)Length.Zero); + Assert.ThrowsExactly(() => p - p); + Assert.ThrowsExactly(() => p * 0.0); + Assert.ThrowsExactly(() => h - h); + Assert.ThrowsExactly(() => HalfLife.From(Duration.Zero)); + + Assert.AreEqual(2.0, (w * 2.0).Value); + Assert.AreEqual(1.0, (Wavelength.FromMeter(3) - Wavelength.FromMeter(2)).Value); + } + + [TestMethod] + public void UnconstrainedOverloadsStillAcceptZero() + { + Assert.AreEqual(0.0, (Distance.FromMeter(1) * 0.0).Value); + Assert.AreEqual(0.0, Distance.From(Length.Zero).Value); + Assert.AreEqual(0.0, (Length.FromMeter(1) * 0.0).Value); + } + + [TestMethod] + public void DivisionByZeroThrowsOnEveryPath() + { + Assert.ThrowsExactly(() => Velocity1D.FromMeterPerSecond(1) / 0.0); + Assert.ThrowsExactly(() => Velocity3D.FromMeterPerSecond(1, 2, 3) / 0.0); + Assert.ThrowsExactly(() => Mass.FromKilogram(1) / Volume.Zero); + Assert.ThrowsExactly(() => Mass.FromKilogram(0) / Volume.Zero); + Assert.ThrowsExactly(() => Velocity1D.FromMeterPerSecond(1) / Duration.Zero); + Assert.ThrowsExactly(() => Velocity3D.FromMeterPerSecond(1, 2, 3) / Duration.Zero); + Assert.ThrowsExactly(() => Velocity3D.Zero.Normalize()); + } + + [TestMethod] + public void DivisionByZeroThrowsTheSameWayForDecimal() + { + Assert.ThrowsExactly(() => Velocity3D.FromMeterPerSecond(1, 2, 3) / 0m); + Assert.ThrowsExactly(() => Mass.FromKilogram(1) / Volume.Zero); + Assert.ThrowsExactly(() => Velocity3D.FromMeterPerSecond(1, 2, 3) / Duration.Zero); + Assert.ThrowsExactly(() => Velocity3D.Zero.Normalize()); + } +} diff --git a/Semantics.Test/Quantities/StorageMathPreciseAndVectorTests.cs b/Semantics.Test/Quantities/StorageMathPreciseAndVectorTests.cs new file mode 100644 index 00000000..32eef760 --- /dev/null +++ b/Semantics.Test/Quantities/StorageMathPreciseAndVectorTests.cs @@ -0,0 +1,88 @@ +// Copyright (c) 2023-2026 ktsu-dev contributors + +namespace ktsu.Semantics.Test.Quantities; + +using System.Numerics; +using ktsu.PreciseNumber; +using ktsu.Semantics.Quantities; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +/// +/// Higher roots that finish for a type with no fixed precision (#457), and vector lengths that do not +/// square their components outright (#327). +/// +[TestClass] +public sealed class StorageMathPreciseAndVectorTests +{ + private static PreciseNumber P(double value) => Of(value); + + private static T Of(double value) + where T : INumber => T.CreateChecked(value); + + private static T Abs(T value) + where T : INumber => T.Abs(value); + + [TestMethod] + [Timeout(20_000, CooperativeCancellation = true)] + public void PreciseCubeRootOfAPerfectCubeIsExact() + { + PreciseNumber root = StorageMath.Cbrt(P(27)); + Assert.IsLessThan(P(1e-30), Abs(root - P(3))); + } + + [TestMethod] + [Timeout(20_000, CooperativeCancellation = true)] + public void PreciseCubeRootOfTwoHasThirtyDigits() + { + PreciseNumber root = StorageMath.Cbrt(P(2)); + PreciseNumber error = Abs((root * root * root) - P(2)); + Assert.IsLessThan(P(1e-30), error); + } + + [TestMethod] + [Timeout(20_000, CooperativeCancellation = true)] + public void PreciseFourthAndFifthRootsFinish() + { + PreciseNumber fourth = StorageMath.RootN(P(3), 4); + PreciseNumber fifth = StorageMath.RootN(P(3), 5); + + Assert.IsLessThan(P(1e-30), Abs((fourth * fourth * fourth * fourth) - P(3))); + Assert.IsLessThan(P(1e-30), Abs((fifth * fifth * fifth * fifth * fifth) - P(3))); + } + + [TestMethod] + public void IntegerVectorLengthsDoNotWrap() + { + Assert.AreEqual(65536, Position3D.FromMeter(65536, 0, 0).Length()); + Assert.AreEqual(65536, Displacement2D.FromMeter(65536, 0).Length()); + Assert.AreEqual(1L << 32, Position3D.FromMeter(1L << 32, 0, 0).Length()); + Assert.AreEqual(50000, Position3D.FromMeter(50000, 0, 0).Length()); + } + + [TestMethod] + public void DecimalVectorLengthPastTheSquareOfItsRange() + { + Position3D far = Position3D.FromMeter(1e15m, 0m, 0m); + + Assert.AreEqual(1e15m, far.Length()); + Assert.AreEqual(1e15m, far.Magnitude().Value); + Assert.AreEqual(1e15m, far.Distance(Position3D.Zero)); + } + + [TestMethod] + public void FloatVectorLengthAndNormalizePastTheSquareOfItsRange() + { + Position3D far = Position3D.FromMeter(1e20f, 0f, 0f); + + Assert.AreEqual(1e20f, far.Length()); + Assert.AreEqual(1f, far.Normalize().X); + } + + [TestMethod] + public void FourComponentLengthIsScaled() + { + Assert.AreEqual(2m, StorageMath.Hypot(1m, 1m, 1m, 1m)); + Assert.AreEqual(2e20m, StorageMath.Hypot(1e20m, 1e20m, 1e20m, 1e20m)); + Assert.AreEqual(13d, StorageMath.Hypot(3d, 4d, 12d)); + } +} From f4c9ef7f1b5981d0a4a3bd43ce4161f1c59e1e5f Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 26 Oct 2026 10:54:57 +0000 Subject: [PATCH 4/8] [patch] Quantities: overloads forward their base's relationship operators (#456) Distance / Duration, Width * Width, Weight * Height and WindVelocity3D * Duration now compile. Each overload declares a copy of every relationship operator its base has with itself on the left; results stay base types. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01RjhaUGAEJWfvbkaV4MjYkY --- .../ActivationEnergy.g.cs | 4 + .../Admittance.g.cs | 4 + .../Airspeed.g.cs | 28 +++ .../Altitude.g.cs | 40 ++++ .../ApertureAngle.g.cs | 8 + .../AtmosphericPressure.g.cs | 12 ++ .../AtomicMass.g.cs | 36 ++++ .../Bandwidth.g.cs | 8 + .../Bearing.g.cs | 4 + .../BulkModulus.g.cs | 12 ++ .../Capacity.g.cs | 32 +++ .../ClockSpeed.g.cs | 8 + .../CrossSectionalArea.g.cs | 36 ++++ .../DecayTime.g.cs | 184 ++++++++++++++++++ .../Depth.g.cs | 40 ++++ .../Diameter.g.cs | 40 ++++ .../Distance.g.cs | 40 ++++ .../Drag.g.cs | 32 +++ .../EMF.g.cs | 40 ++++ .../EnergyFluxDensity.g.cs | 4 + .../EnzymeActivity.g.cs | 4 + .../FieldOfView.g.cs | 8 + .../FlowSpeed.g.cs | 28 +++ .../Friction.g.cs | 32 +++ .../Gain.g.cs | 24 +++ .../GaugePressure.g.cs | 12 ++ .../GravitationalAcceleration.g.cs | 20 ++ .../GravitationalField3D.g.cs | 6 + .../GroundSpeed.g.cs | 28 +++ .../GroupVelocity.g.cs | 28 +++ .../HalfLife.g.cs | 184 ++++++++++++++++++ .../Heading.g.cs | 4 + .../Heat.g.cs | 40 ++++ .../HeatCapacity.g.cs | 12 ++ .../HeatFlowRate.g.cs | 36 ++++ .../HeatFlux.g.cs | 4 + .../Height.g.cs | 40 ++++ .../Impedance.g.cs | 8 + .../KineticEnergy.g.cs | 40 ++++ .../Latency.g.cs | 184 ++++++++++++++++++ .../Lift.g.cs | 32 +++ .../MachNumber.g.cs | 24 +++ .../MolarEnthalpy.g.cs | 4 + .../NoiseReductionCoefficient.g.cs | 24 +++ .../NormalForce.g.cs | 32 +++ .../Offset.g.cs | 4 + .../Perimeter.g.cs | 40 ++++ .../Period.g.cs | 184 ++++++++++++++++++ .../Phase.g.cs | 4 + .../PhaseVelocity.g.cs | 28 +++ .../Pitch.g.cs | 8 + .../Position3D.g.cs | 3 + .../PotentialEnergy.g.cs | 40 ++++ .../Radius.g.cs | 40 ++++ .../ReflectionCoefficient.g.cs | 8 + .../RefractiveIndex.g.cs | 24 +++ .../ReverberationTime.g.cs | 184 ++++++++++++++++++ .../ReynoldsNumber.g.cs | 24 +++ .../Rotation.g.cs | 4 + .../SamplingRate.g.cs | 8 + .../ShearModulus.g.cs | 12 ++ .../SoundAbsorption.g.cs | 24 +++ .../SoundIntensity.g.cs | 4 + .../SoundPower.g.cs | 36 ++++ .../SoundPressure.g.cs | 12 ++ .../SoundSpeed.g.cs | 28 +++ .../SoundTransmissionClass.g.cs | 24 +++ .../SpecificEntropy.g.cs | 4 + .../SpecificGravity.g.cs | 24 +++ .../SpecificKineticEnergy.g.cs | 4 + .../StandardGravitationalParameter.g.cs | 8 + .../Stress.g.cs | 12 ++ .../SurfaceArea.g.cs | 36 ++++ .../Tension.g.cs | 32 +++ .../ThermalDiffusivity.g.cs | 4 + .../ThermalEnergy.g.cs | 40 ++++ .../Thickness.g.cs | 40 ++++ .../Thrust.g.cs | 32 +++ .../ThrustVector.g.cs | 3 + .../TimeConstant.g.cs | 184 ++++++++++++++++++ .../Translation3D.g.cs | 3 + .../VoltageDrop.g.cs | 40 ++++ .../Wavelength.g.cs | 40 ++++ .../Weight.g.cs | 32 +++ .../WeightVector.g.cs | 3 + .../Width.g.cs | 40 ++++ .../WindSpeed.g.cs | 28 +++ .../WindVelocity3D.g.cs | 6 + .../Work.g.cs | 40 ++++ .../YoungsModulus.g.cs | 12 ++ .../Generators/QuantitiesGenerator.cs | 63 ++++++ .../GeneratorOutputInvariantTests.cs | 18 +- .../OverloadRelationshipOperatorTests.cs | 68 +++++++ docs/migration-guide-2.0.md | 5 +- docs/physics-generator.md | 3 +- docs/strategy-unified-vector-quantities.md | 8 +- 96 files changed, 3037 insertions(+), 8 deletions(-) create mode 100644 Semantics.Test/Quantities/OverloadRelationshipOperatorTests.cs diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ActivationEnergy.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ActivationEnergy.g.cs index 2a2f6607..f5fad16d 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ActivationEnergy.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ActivationEnergy.g.cs @@ -134,5 +134,9 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two ActivationEnergy values, returning the absolute difference as a non-negative ActivationEnergy. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static ActivationEnergy operator -(ActivationEnergy left, ActivationEnergy right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// ActivationEnergy * AmountOfSubstance = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(ActivationEnergy left, AmountOfSubstance right) => (MolarEnergy)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Admittance.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Admittance.g.cs index 9f431079..ce892bc8 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Admittance.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Admittance.g.cs @@ -118,5 +118,9 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Admittance values, returning the absolute difference as a non-negative Admittance. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Admittance operator -(Admittance left, Admittance right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Admittance * VoltageMagnitude = CurrentMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static CurrentMagnitude operator *(Admittance left, VoltageMagnitude right) => (Conductance)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Airspeed.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Airspeed.g.cs index ad1418b1..f4bcf115 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Airspeed.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Airspeed.g.cs @@ -158,5 +158,33 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Airspeed values, returning the absolute difference as a non-negative Airspeed. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Airspeed operator -(Airspeed left, Airspeed right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Airspeed * Mass = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(Airspeed left, Mass right) => (Speed)left * right; + + /// Airspeed * Duration = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator *(Airspeed left, Duration right) => (Speed)left * right; + + /// Airspeed / Duration = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator /(Airspeed left, Duration right) => (Speed)left / right; + + /// Airspeed / AccelerationMagnitude = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(Airspeed left, AccelerationMagnitude right) => (Speed)left / right; + + /// Airspeed / Length = Frequency, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Frequency operator /(Airspeed left, Length right) => (Speed)left / right; + + /// Airspeed / Frequency = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(Airspeed left, Frequency right) => (Speed)left / right; + + /// Airspeed * ForceMagnitude = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(Airspeed left, ForceMagnitude right) => (Speed)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Altitude.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Altitude.g.cs index daca6559..3fab1ea4 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Altitude.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Altitude.g.cs @@ -206,5 +206,45 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Altitude values, returning the absolute difference as a non-negative Altitude. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Altitude operator -(Altitude left, Altitude right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Altitude * Length = Area, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Area operator *(Altitude left, Length right) => (Length)left * right; + + /// Altitude * Area = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator *(Altitude left, Area right) => (Length)left * right; + + /// Altitude / Duration = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator /(Altitude left, Duration right) => (Length)left / right; + + /// Altitude / Speed = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(Altitude left, Speed right) => (Length)left / right; + + /// Altitude * Frequency = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(Altitude left, Frequency right) => (Length)left * right; + + /// Altitude * ForceMagnitude = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Altitude left, ForceMagnitude right) => (Length)left * right; + + /// Altitude * ElectricFieldMagnitude = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator *(Altitude left, ElectricFieldMagnitude right) => (Length)left * right; + + /// Altitude * ElectricField1D = Voltage, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Voltage operator *(Altitude left, ElectricField1D right) => (Length)left * right; + + /// Altitude * SurfaceTension = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(Altitude left, SurfaceTension right) => (Length)left * right; + + /// Altitude * SpecificEnergyMagnitude = GravitationalParameter, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static GravitationalParameter operator *(Altitude left, SpecificEnergyMagnitude right) => (Length)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ApertureAngle.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ApertureAngle.g.cs index 00d656ae..e17b072e 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ApertureAngle.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ApertureAngle.g.cs @@ -150,5 +150,13 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two ApertureAngle values, returning the absolute difference as a non-negative ApertureAngle. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static ApertureAngle operator -(ApertureAngle left, ApertureAngle right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// ApertureAngle / Duration = AngularSpeed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularSpeed operator /(ApertureAngle left, Duration right) => (Angle)left / right; + + /// ApertureAngle / AngularSpeed = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(ApertureAngle left, AngularSpeed right) => (Angle)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AtmosphericPressure.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AtmosphericPressure.g.cs index 2f318332..bec8138b 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AtmosphericPressure.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AtmosphericPressure.g.cs @@ -158,5 +158,17 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two AtmosphericPressure values, returning the absolute difference as a non-negative AtmosphericPressure. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static AtmosphericPressure operator -(AtmosphericPressure left, AtmosphericPressure right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// AtmosphericPressure * Area = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(AtmosphericPressure left, Area right) => (Pressure)left * right; + + /// AtmosphericPressure * Volume = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(AtmosphericPressure left, Volume right) => (Pressure)left * right; + + /// AtmosphericPressure * Sensitivity = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator *(AtmosphericPressure left, Sensitivity right) => (Pressure)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AtomicMass.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AtomicMass.g.cs index 4707aea7..97428902 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AtomicMass.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AtomicMass.g.cs @@ -174,5 +174,41 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two AtomicMass values, returning the absolute difference as a non-negative AtomicMass. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static AtomicMass operator -(AtomicMass left, AtomicMass right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// AtomicMass * AccelerationMagnitude = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(AtomicMass left, AccelerationMagnitude right) => (Mass)left * right; + + /// AtomicMass * Speed = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(AtomicMass left, Speed right) => (Mass)left * right; + + /// AtomicMass / Volume = Density, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Density operator /(AtomicMass left, Volume right) => (Mass)left / right; + + /// AtomicMass / Density = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator /(AtomicMass left, Density right) => (Mass)left / right; + + /// AtomicMass * SpecificHeat = Entropy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Entropy operator *(AtomicMass left, SpecificHeat right) => (Mass)left * right; + + /// AtomicMass / Duration = MassFlowRate, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MassFlowRate operator /(AtomicMass left, Duration right) => (Mass)left / right; + + /// AtomicMass / MassFlowRate = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(AtomicMass left, MassFlowRate right) => (Mass)left / right; + + /// AtomicMass / AmountOfSubstance = MolarMass, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MolarMass operator /(AtomicMass left, AmountOfSubstance right) => (Mass)left / right; + + /// AtomicMass / MolarMass = AmountOfSubstance, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AmountOfSubstance operator /(AtomicMass left, MolarMass right) => (Mass)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Bandwidth.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Bandwidth.g.cs index 487d02ef..c2679902 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Bandwidth.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Bandwidth.g.cs @@ -134,5 +134,13 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Bandwidth values, returning the absolute difference as a non-negative Bandwidth. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Bandwidth operator -(Bandwidth left, Bandwidth right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Bandwidth * Duration = Ratio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Ratio operator *(Bandwidth left, Duration right) => (Frequency)left * right; + + /// Bandwidth * Length = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(Bandwidth left, Length right) => (Frequency)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Bearing.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Bearing.g.cs index c9f710bd..9b244283 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Bearing.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Bearing.g.cs @@ -149,5 +149,9 @@ namespace ktsu.Semantics.Quantities; /// Creates a Bearing from a SignedAngle value. public static Bearing From(SignedAngle value) => Create(value.Value); + + /// Bearing / Duration = AngularVelocity1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularVelocity1D operator /(Bearing left, Duration right) => (SignedAngle)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/BulkModulus.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/BulkModulus.g.cs index 658b561a..d19f2051 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/BulkModulus.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/BulkModulus.g.cs @@ -158,5 +158,17 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two BulkModulus values, returning the absolute difference as a non-negative BulkModulus. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static BulkModulus operator -(BulkModulus left, BulkModulus right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// BulkModulus * Area = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(BulkModulus left, Area right) => (Pressure)left * right; + + /// BulkModulus * Volume = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(BulkModulus left, Volume right) => (Pressure)left * right; + + /// BulkModulus * Sensitivity = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator *(BulkModulus left, Sensitivity right) => (Pressure)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Capacity.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Capacity.g.cs index 25c1751f..d9c5dae4 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Capacity.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Capacity.g.cs @@ -198,5 +198,37 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Capacity values, returning the absolute difference as a non-negative Capacity. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Capacity operator -(Capacity left, Capacity right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Capacity / Length = Area, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Area operator /(Capacity left, Length right) => (Volume)left / right; + + /// Capacity / Area = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(Capacity left, Area right) => (Volume)left / right; + + /// Capacity * Pressure = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Capacity left, Pressure right) => (Volume)left * right; + + /// Capacity * Density = Mass, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Mass operator *(Capacity left, Density right) => (Volume)left * right; + + /// Capacity * Concentration = AmountOfSubstance, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AmountOfSubstance operator *(Capacity left, Concentration right) => (Volume)left * right; + + /// Capacity / Duration = VolumetricFlowRate, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VolumetricFlowRate operator /(Capacity left, Duration right) => (Volume)left / right; + + /// Capacity / VolumetricFlowRate = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(Capacity left, VolumetricFlowRate right) => (Volume)left / right; + + /// Capacity * ElectricPowerDensity = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(Capacity left, ElectricPowerDensity right) => (Volume)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ClockSpeed.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ClockSpeed.g.cs index 7b5f4ea4..79d398b6 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ClockSpeed.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ClockSpeed.g.cs @@ -134,5 +134,13 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two ClockSpeed values, returning the absolute difference as a non-negative ClockSpeed. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static ClockSpeed operator -(ClockSpeed left, ClockSpeed right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// ClockSpeed * Duration = Ratio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Ratio operator *(ClockSpeed left, Duration right) => (Frequency)left * right; + + /// ClockSpeed * Length = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(ClockSpeed left, Length right) => (Frequency)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/CrossSectionalArea.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/CrossSectionalArea.g.cs index dacce608..f7e3b5e0 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/CrossSectionalArea.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/CrossSectionalArea.g.cs @@ -174,5 +174,41 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two CrossSectionalArea values, returning the absolute difference as a non-negative CrossSectionalArea. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static CrossSectionalArea operator -(CrossSectionalArea left, CrossSectionalArea right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// CrossSectionalArea / Length = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(CrossSectionalArea left, Length right) => (Area)left / right; + + /// CrossSectionalArea * Length = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator *(CrossSectionalArea left, Length right) => (Area)left * right; + + /// CrossSectionalArea * Pressure = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(CrossSectionalArea left, Pressure right) => (Area)left * right; + + /// CrossSectionalArea * ElectricFieldMagnitude = ElectricFlux, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ElectricFlux operator *(CrossSectionalArea left, ElectricFieldMagnitude right) => (Area)left * right; + + /// CrossSectionalArea * Illuminance = LuminousFlux, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static LuminousFlux operator *(CrossSectionalArea left, Illuminance right) => (Area)left * right; + + /// CrossSectionalArea * MagneticFluxDensityMagnitude = MagneticFlux, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MagneticFlux operator *(CrossSectionalArea left, MagneticFluxDensityMagnitude right) => (Area)left * right; + + /// CrossSectionalArea * Irradiance = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(CrossSectionalArea left, Irradiance right) => (Area)left * right; + + /// CrossSectionalArea * Luminance = LuminousIntensity, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static LuminousIntensity operator *(CrossSectionalArea left, Luminance right) => (Area)left * right; + + /// CrossSectionalArea * AccelerationMagnitude = GravitationalParameter, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static GravitationalParameter operator *(CrossSectionalArea left, AccelerationMagnitude right) => (Area)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/DecayTime.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/DecayTime.g.cs index 355641c1..8af06c67 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/DecayTime.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/DecayTime.g.cs @@ -182,5 +182,189 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two DecayTime values, returning the absolute difference as a non-negative DecayTime. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static DecayTime operator -(DecayTime left, DecayTime right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// DecayTime * CurrentMagnitude = ChargeMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ChargeMagnitude operator *(DecayTime left, CurrentMagnitude right) => (Duration)left * right; + + /// DecayTime * Current1D = Charge, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Charge operator *(DecayTime left, Current1D right) => (Duration)left * right; + + /// DecayTime * Speed = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator *(DecayTime left, Speed right) => (Duration)left * right; + + /// DecayTime * Velocity1D = Displacement1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement1D operator *(DecayTime left, Velocity1D right) => (Duration)left * right; + + /// DecayTime * Velocity2D = Displacement2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement2D operator *(DecayTime left, Velocity2D right) => (Duration)left * right; + + /// DecayTime * Velocity3D = Displacement3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement3D operator *(DecayTime left, Velocity3D right) => (Duration)left * right; + + /// DecayTime * Velocity4D = Displacement4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement4D operator *(DecayTime left, Velocity4D right) => (Duration)left * right; + + /// DecayTime * AccelerationMagnitude = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(DecayTime left, AccelerationMagnitude right) => (Duration)left * right; + + /// DecayTime * Acceleration1D = Velocity1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity1D operator *(DecayTime left, Acceleration1D right) => (Duration)left * right; + + /// DecayTime * Acceleration2D = Velocity2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity2D operator *(DecayTime left, Acceleration2D right) => (Duration)left * right; + + /// DecayTime * Acceleration3D = Velocity3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity3D operator *(DecayTime left, Acceleration3D right) => (Duration)left * right; + + /// DecayTime * Acceleration4D = Velocity4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity4D operator *(DecayTime left, Acceleration4D right) => (Duration)left * right; + + /// DecayTime * JerkMagnitude = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator *(DecayTime left, JerkMagnitude right) => (Duration)left * right; + + /// DecayTime * Jerk1D = Acceleration1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration1D operator *(DecayTime left, Jerk1D right) => (Duration)left * right; + + /// DecayTime * Jerk2D = Acceleration2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration2D operator *(DecayTime left, Jerk2D right) => (Duration)left * right; + + /// DecayTime * Jerk3D = Acceleration3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration3D operator *(DecayTime left, Jerk3D right) => (Duration)left * right; + + /// DecayTime * Jerk4D = Acceleration4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration4D operator *(DecayTime left, Jerk4D right) => (Duration)left * right; + + /// DecayTime * SnapMagnitude = JerkMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static JerkMagnitude operator *(DecayTime left, SnapMagnitude right) => (Duration)left * right; + + /// DecayTime * Snap1D = Jerk1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk1D operator *(DecayTime left, Snap1D right) => (Duration)left * right; + + /// DecayTime * Snap2D = Jerk2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk2D operator *(DecayTime left, Snap2D right) => (Duration)left * right; + + /// DecayTime * Snap3D = Jerk3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk3D operator *(DecayTime left, Snap3D right) => (Duration)left * right; + + /// DecayTime * Snap4D = Jerk4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk4D operator *(DecayTime left, Snap4D right) => (Duration)left * right; + + /// DecayTime * Frequency = Ratio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Ratio operator *(DecayTime left, Frequency right) => (Duration)left * right; + + /// DecayTime * AngularSpeed = Angle, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Angle operator *(DecayTime left, AngularSpeed right) => (Duration)left * right; + + /// DecayTime * AngularVelocity1D = SignedAngle, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SignedAngle operator *(DecayTime left, AngularVelocity1D right) => (Duration)left * right; + + /// DecayTime * AngularVelocity3D = AngularDisplacement3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularDisplacement3D operator *(DecayTime left, AngularVelocity3D right) => (Duration)left * right; + + /// DecayTime * AngularAccelerationMagnitude = AngularSpeed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularSpeed operator *(DecayTime left, AngularAccelerationMagnitude right) => (Duration)left * right; + + /// DecayTime * AngularAcceleration1D = AngularVelocity1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularVelocity1D operator *(DecayTime left, AngularAcceleration1D right) => (Duration)left * right; + + /// DecayTime * AngularAcceleration3D = AngularVelocity3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularVelocity3D operator *(DecayTime left, AngularAcceleration3D right) => (Duration)left * right; + + /// DecayTime * AngularJerkMagnitude = AngularAccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularAccelerationMagnitude operator *(DecayTime left, AngularJerkMagnitude right) => (Duration)left * right; + + /// DecayTime * AngularJerk1D = AngularAcceleration1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularAcceleration1D operator *(DecayTime left, AngularJerk1D right) => (Duration)left * right; + + /// DecayTime * AngularJerk3D = AngularAcceleration3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularAcceleration3D operator *(DecayTime left, AngularJerk3D right) => (Duration)left * right; + + /// DecayTime * TorqueMagnitude = AngularMomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularMomentumMagnitude operator *(DecayTime left, TorqueMagnitude right) => (Duration)left * right; + + /// DecayTime * Torque1D = AngularMomentum1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularMomentum1D operator *(DecayTime left, Torque1D right) => (Duration)left * right; + + /// DecayTime * Torque3D = AngularMomentum3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularMomentum3D operator *(DecayTime left, Torque3D right) => (Duration)left * right; + + /// DecayTime * ForceMagnitude = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(DecayTime left, ForceMagnitude right) => (Duration)left * right; + + /// DecayTime * Force1D = Momentum1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum1D operator *(DecayTime left, Force1D right) => (Duration)left * right; + + /// DecayTime * Force2D = Momentum2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum2D operator *(DecayTime left, Force2D right) => (Duration)left * right; + + /// DecayTime * Force3D = Momentum3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum3D operator *(DecayTime left, Force3D right) => (Duration)left * right; + + /// DecayTime * Force4D = Momentum4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum4D operator *(DecayTime left, Force4D right) => (Duration)left * right; + + /// DecayTime * Power = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(DecayTime left, Power right) => (Duration)left * right; + + /// DecayTime * VolumetricFlowRate = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator *(DecayTime left, VolumetricFlowRate right) => (Duration)left * right; + + /// DecayTime * MassFlowRate = Mass, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Mass operator *(DecayTime left, MassFlowRate right) => (Duration)left * right; + + /// DecayTime * CatalyticActivity = AmountOfSubstance, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AmountOfSubstance operator *(DecayTime left, CatalyticActivity right) => (Duration)left * right; + + /// DecayTime * ReactionRate = Concentration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Concentration operator *(DecayTime left, ReactionRate right) => (Duration)left * right; + + /// DecayTime * VoltageMagnitude = MagneticFlux, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MagneticFlux operator *(DecayTime left, VoltageMagnitude right) => (Duration)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Depth.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Depth.g.cs index 965da4c7..23ec5078 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Depth.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Depth.g.cs @@ -206,5 +206,45 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Depth values, returning the absolute difference as a non-negative Depth. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Depth operator -(Depth left, Depth right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Depth * Length = Area, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Area operator *(Depth left, Length right) => (Length)left * right; + + /// Depth * Area = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator *(Depth left, Area right) => (Length)left * right; + + /// Depth / Duration = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator /(Depth left, Duration right) => (Length)left / right; + + /// Depth / Speed = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(Depth left, Speed right) => (Length)left / right; + + /// Depth * Frequency = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(Depth left, Frequency right) => (Length)left * right; + + /// Depth * ForceMagnitude = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Depth left, ForceMagnitude right) => (Length)left * right; + + /// Depth * ElectricFieldMagnitude = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator *(Depth left, ElectricFieldMagnitude right) => (Length)left * right; + + /// Depth * ElectricField1D = Voltage, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Voltage operator *(Depth left, ElectricField1D right) => (Length)left * right; + + /// Depth * SurfaceTension = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(Depth left, SurfaceTension right) => (Length)left * right; + + /// Depth * SpecificEnergyMagnitude = GravitationalParameter, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static GravitationalParameter operator *(Depth left, SpecificEnergyMagnitude right) => (Length)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Diameter.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Diameter.g.cs index 0ddbc05c..46177401 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Diameter.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Diameter.g.cs @@ -207,6 +207,46 @@ namespace ktsu.Semantics.Quantities; [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Diameter operator -(Diameter left, Diameter right) => Create(T.Abs(left.Quantity - right.Quantity)); + /// Diameter * Length = Area, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Area operator *(Diameter left, Length right) => (Length)left * right; + + /// Diameter * Area = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator *(Diameter left, Area right) => (Length)left * right; + + /// Diameter / Duration = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator /(Diameter left, Duration right) => (Length)left / right; + + /// Diameter / Speed = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(Diameter left, Speed right) => (Length)left / right; + + /// Diameter * Frequency = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(Diameter left, Frequency right) => (Length)left * right; + + /// Diameter * ForceMagnitude = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Diameter left, ForceMagnitude right) => (Length)left * right; + + /// Diameter * ElectricFieldMagnitude = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator *(Diameter left, ElectricFieldMagnitude right) => (Length)left * right; + + /// Diameter * ElectricField1D = Voltage, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Voltage operator *(Diameter left, ElectricField1D right) => (Length)left * right; + + /// Diameter * SurfaceTension = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(Diameter left, SurfaceTension right) => (Length)left * right; + + /// Diameter * SpecificEnergyMagnitude = GravitationalParameter, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static GravitationalParameter operator *(Diameter left, SpecificEnergyMagnitude right) => (Length)left * right; + /// Converts this Diameter to a Radius. public Radius ToRadius() => Radius.Create(Value / T.CreateChecked(2)); diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Distance.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Distance.g.cs index 19b09266..74180f16 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Distance.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Distance.g.cs @@ -206,5 +206,45 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Distance values, returning the absolute difference as a non-negative Distance. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Distance operator -(Distance left, Distance right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Distance * Length = Area, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Area operator *(Distance left, Length right) => (Length)left * right; + + /// Distance * Area = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator *(Distance left, Area right) => (Length)left * right; + + /// Distance / Duration = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator /(Distance left, Duration right) => (Length)left / right; + + /// Distance / Speed = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(Distance left, Speed right) => (Length)left / right; + + /// Distance * Frequency = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(Distance left, Frequency right) => (Length)left * right; + + /// Distance * ForceMagnitude = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Distance left, ForceMagnitude right) => (Length)left * right; + + /// Distance * ElectricFieldMagnitude = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator *(Distance left, ElectricFieldMagnitude right) => (Length)left * right; + + /// Distance * ElectricField1D = Voltage, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Voltage operator *(Distance left, ElectricField1D right) => (Length)left * right; + + /// Distance * SurfaceTension = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(Distance left, SurfaceTension right) => (Length)left * right; + + /// Distance * SpecificEnergyMagnitude = GravitationalParameter, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static GravitationalParameter operator *(Distance left, SpecificEnergyMagnitude right) => (Length)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Drag.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Drag.g.cs index 7dd178e5..10676146 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Drag.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Drag.g.cs @@ -142,5 +142,37 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Drag values, returning the absolute difference as a non-negative Drag. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Drag operator -(Drag left, Drag right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Drag / AccelerationMagnitude = Mass, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Mass operator /(Drag left, AccelerationMagnitude right) => (ForceMagnitude)left / right; + + /// Drag / Mass = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator /(Drag left, Mass right) => (ForceMagnitude)left / right; + + /// Drag * Length = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Drag left, Length right) => (ForceMagnitude)left * right; + + /// Drag * Duration = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(Drag left, Duration right) => (ForceMagnitude)left * right; + + /// Drag * Speed = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(Drag left, Speed right) => (ForceMagnitude)left * right; + + /// Drag / Area = Pressure, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Pressure operator /(Drag left, Area right) => (ForceMagnitude)left / right; + + /// Drag / Length = SurfaceTension, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SurfaceTension operator /(Drag left, Length right) => (ForceMagnitude)left / right; + + /// Drag / SurfaceTension = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(Drag left, SurfaceTension right) => (ForceMagnitude)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/EMF.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/EMF.g.cs index e8e2a2a8..089582b1 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/EMF.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/EMF.g.cs @@ -126,5 +126,45 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two EMF values, returning the absolute difference as a non-negative EMF. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static EMF operator -(EMF left, EMF right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// EMF / Resistance = CurrentMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static CurrentMagnitude operator /(EMF left, Resistance right) => (VoltageMagnitude)left / right; + + /// EMF / CurrentMagnitude = Resistance, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Resistance operator /(EMF left, CurrentMagnitude right) => (VoltageMagnitude)left / right; + + /// EMF * CurrentMagnitude = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(EMF left, CurrentMagnitude right) => (VoltageMagnitude)left * right; + + /// EMF / Length = ElectricFieldMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ElectricFieldMagnitude operator /(EMF left, Length right) => (VoltageMagnitude)left / right; + + /// EMF / ElectricFieldMagnitude = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(EMF left, ElectricFieldMagnitude right) => (VoltageMagnitude)left / right; + + /// EMF * Capacitance = ChargeMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ChargeMagnitude operator *(EMF left, Capacitance right) => (VoltageMagnitude)left * right; + + /// EMF * Conductance = CurrentMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static CurrentMagnitude operator *(EMF left, Conductance right) => (VoltageMagnitude)left * right; + + /// EMF * Duration = MagneticFlux, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MagneticFlux operator *(EMF left, Duration right) => (VoltageMagnitude)left * right; + + /// EMF / Pressure = Sensitivity, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Sensitivity operator /(EMF left, Pressure right) => (VoltageMagnitude)left / right; + + /// EMF / Sensitivity = Pressure, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Pressure operator /(EMF left, Sensitivity right) => (VoltageMagnitude)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/EnergyFluxDensity.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/EnergyFluxDensity.g.cs index 84643bcd..97fa3ea0 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/EnergyFluxDensity.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/EnergyFluxDensity.g.cs @@ -118,5 +118,9 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two EnergyFluxDensity values, returning the absolute difference as a non-negative EnergyFluxDensity. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static EnergyFluxDensity operator -(EnergyFluxDensity left, EnergyFluxDensity right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// EnergyFluxDensity * Area = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(EnergyFluxDensity left, Area right) => (Irradiance)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/EnzymeActivity.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/EnzymeActivity.g.cs index fe485d3b..a0f34ca4 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/EnzymeActivity.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/EnzymeActivity.g.cs @@ -126,5 +126,9 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two EnzymeActivity values, returning the absolute difference as a non-negative EnzymeActivity. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static EnzymeActivity operator -(EnzymeActivity left, EnzymeActivity right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// EnzymeActivity * Duration = AmountOfSubstance, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AmountOfSubstance operator *(EnzymeActivity left, Duration right) => (CatalyticActivity)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/FieldOfView.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/FieldOfView.g.cs index fa8435ee..36a68f87 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/FieldOfView.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/FieldOfView.g.cs @@ -150,5 +150,13 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two FieldOfView values, returning the absolute difference as a non-negative FieldOfView. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static FieldOfView operator -(FieldOfView left, FieldOfView right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// FieldOfView / Duration = AngularSpeed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularSpeed operator /(FieldOfView left, Duration right) => (Angle)left / right; + + /// FieldOfView / AngularSpeed = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(FieldOfView left, AngularSpeed right) => (Angle)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/FlowSpeed.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/FlowSpeed.g.cs index c377864a..a46338c8 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/FlowSpeed.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/FlowSpeed.g.cs @@ -158,5 +158,33 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two FlowSpeed values, returning the absolute difference as a non-negative FlowSpeed. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static FlowSpeed operator -(FlowSpeed left, FlowSpeed right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// FlowSpeed * Mass = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(FlowSpeed left, Mass right) => (Speed)left * right; + + /// FlowSpeed * Duration = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator *(FlowSpeed left, Duration right) => (Speed)left * right; + + /// FlowSpeed / Duration = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator /(FlowSpeed left, Duration right) => (Speed)left / right; + + /// FlowSpeed / AccelerationMagnitude = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(FlowSpeed left, AccelerationMagnitude right) => (Speed)left / right; + + /// FlowSpeed / Length = Frequency, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Frequency operator /(FlowSpeed left, Length right) => (Speed)left / right; + + /// FlowSpeed / Frequency = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(FlowSpeed left, Frequency right) => (Speed)left / right; + + /// FlowSpeed * ForceMagnitude = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(FlowSpeed left, ForceMagnitude right) => (Speed)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Friction.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Friction.g.cs index fb04af6b..bdce8d5f 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Friction.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Friction.g.cs @@ -142,5 +142,37 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Friction values, returning the absolute difference as a non-negative Friction. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Friction operator -(Friction left, Friction right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Friction / AccelerationMagnitude = Mass, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Mass operator /(Friction left, AccelerationMagnitude right) => (ForceMagnitude)left / right; + + /// Friction / Mass = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator /(Friction left, Mass right) => (ForceMagnitude)left / right; + + /// Friction * Length = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Friction left, Length right) => (ForceMagnitude)left * right; + + /// Friction * Duration = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(Friction left, Duration right) => (ForceMagnitude)left * right; + + /// Friction * Speed = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(Friction left, Speed right) => (ForceMagnitude)left * right; + + /// Friction / Area = Pressure, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Pressure operator /(Friction left, Area right) => (ForceMagnitude)left / right; + + /// Friction / Length = SurfaceTension, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SurfaceTension operator /(Friction left, Length right) => (ForceMagnitude)left / right; + + /// Friction / SurfaceTension = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(Friction left, SurfaceTension right) => (ForceMagnitude)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Gain.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Gain.g.cs index d21d72a3..491cf06a 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Gain.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Gain.g.cs @@ -190,5 +190,29 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Gain values, returning the absolute difference as a non-negative Gain. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Gain operator -(Gain left, Gain right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Gain * Ratio = Ratio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Ratio operator *(Gain left, Ratio right) => (Ratio)left * right; + + /// Gain * SignedRatio = SignedRatio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SignedRatio operator *(Gain left, SignedRatio right) => (Ratio)left * right; + + /// Gain / Duration = Frequency, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Frequency operator /(Gain left, Duration right) => (Ratio)left / right; + + /// Gain / Frequency = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(Gain left, Frequency right) => (Ratio)left / right; + + /// Gain / Temperature = ThermalExpansionCoefficient, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ThermalExpansionCoefficient operator /(Gain left, Temperature right) => (Ratio)left / right; + + /// Gain / ThermalExpansionCoefficient = Temperature, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Temperature operator /(Gain left, ThermalExpansionCoefficient right) => (Ratio)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GaugePressure.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GaugePressure.g.cs index 38b9b172..50046f7f 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GaugePressure.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GaugePressure.g.cs @@ -158,5 +158,17 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two GaugePressure values, returning the absolute difference as a non-negative GaugePressure. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static GaugePressure operator -(GaugePressure left, GaugePressure right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// GaugePressure * Area = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(GaugePressure left, Area right) => (Pressure)left * right; + + /// GaugePressure * Volume = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(GaugePressure left, Volume right) => (Pressure)left * right; + + /// GaugePressure * Sensitivity = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator *(GaugePressure left, Sensitivity right) => (Pressure)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalAcceleration.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalAcceleration.g.cs index 0e23edf7..aabb5ad8 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalAcceleration.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalAcceleration.g.cs @@ -126,5 +126,25 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two GravitationalAcceleration values, returning the absolute difference as a non-negative GravitationalAcceleration. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static GravitationalAcceleration operator -(GravitationalAcceleration left, GravitationalAcceleration right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// GravitationalAcceleration * Mass = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(GravitationalAcceleration left, Mass right) => (AccelerationMagnitude)left * right; + + /// GravitationalAcceleration * Duration = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(GravitationalAcceleration left, Duration right) => (AccelerationMagnitude)left * right; + + /// GravitationalAcceleration / Duration = JerkMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static JerkMagnitude operator /(GravitationalAcceleration left, Duration right) => (AccelerationMagnitude)left / right; + + /// GravitationalAcceleration / JerkMagnitude = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(GravitationalAcceleration left, JerkMagnitude right) => (AccelerationMagnitude)left / right; + + /// GravitationalAcceleration * Area = GravitationalParameter, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static GravitationalParameter operator *(GravitationalAcceleration left, Area right) => (AccelerationMagnitude)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalField3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalField3D.g.cs index 6423eb27..d8ea8de6 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalField3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalField3D.g.cs @@ -132,6 +132,12 @@ public GravitationalField3D Normalize() /// Negates a vector. public static GravitationalField3D operator -(GravitationalField3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; + /// GravitationalField3D * Duration = Velocity3D, through . + public static Velocity3D operator *(GravitationalField3D left, Duration right) => (Acceleration3D)left * right; + + /// GravitationalField3D / Duration = Jerk3D, through . + public static Jerk3D operator /(GravitationalField3D left, Duration right) => (Acceleration3D)left / right; + /// Implicit conversion to Acceleration3D. public static implicit operator Acceleration3D(GravitationalField3D value) => new() { X = value.X, Y = value.Y, Z = value.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GroundSpeed.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GroundSpeed.g.cs index e74a6c44..5ea8c760 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GroundSpeed.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GroundSpeed.g.cs @@ -158,5 +158,33 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two GroundSpeed values, returning the absolute difference as a non-negative GroundSpeed. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static GroundSpeed operator -(GroundSpeed left, GroundSpeed right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// GroundSpeed * Mass = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(GroundSpeed left, Mass right) => (Speed)left * right; + + /// GroundSpeed * Duration = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator *(GroundSpeed left, Duration right) => (Speed)left * right; + + /// GroundSpeed / Duration = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator /(GroundSpeed left, Duration right) => (Speed)left / right; + + /// GroundSpeed / AccelerationMagnitude = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(GroundSpeed left, AccelerationMagnitude right) => (Speed)left / right; + + /// GroundSpeed / Length = Frequency, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Frequency operator /(GroundSpeed left, Length right) => (Speed)left / right; + + /// GroundSpeed / Frequency = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(GroundSpeed left, Frequency right) => (Speed)left / right; + + /// GroundSpeed * ForceMagnitude = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(GroundSpeed left, ForceMagnitude right) => (Speed)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GroupVelocity.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GroupVelocity.g.cs index 985c2a1a..55fac806 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GroupVelocity.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GroupVelocity.g.cs @@ -158,5 +158,33 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two GroupVelocity values, returning the absolute difference as a non-negative GroupVelocity. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static GroupVelocity operator -(GroupVelocity left, GroupVelocity right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// GroupVelocity * Mass = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(GroupVelocity left, Mass right) => (Speed)left * right; + + /// GroupVelocity * Duration = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator *(GroupVelocity left, Duration right) => (Speed)left * right; + + /// GroupVelocity / Duration = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator /(GroupVelocity left, Duration right) => (Speed)left / right; + + /// GroupVelocity / AccelerationMagnitude = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(GroupVelocity left, AccelerationMagnitude right) => (Speed)left / right; + + /// GroupVelocity / Length = Frequency, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Frequency operator /(GroupVelocity left, Length right) => (Speed)left / right; + + /// GroupVelocity / Frequency = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(GroupVelocity left, Frequency right) => (Speed)left / right; + + /// GroupVelocity * ForceMagnitude = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(GroupVelocity left, ForceMagnitude right) => (Speed)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HalfLife.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HalfLife.g.cs index af1eae3e..a6705434 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HalfLife.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HalfLife.g.cs @@ -182,5 +182,189 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two HalfLife values, returning the absolute difference as a positive HalfLife. Throws when the two are equal, since a HalfLife cannot be zero; widen to first for a difference that may be. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static HalfLife operator -(HalfLife left, HalfLife right) => Create(Vector0Guards.EnsurePositive(T.Abs(left.Quantity - right.Quantity), nameof(right))); + + /// HalfLife * CurrentMagnitude = ChargeMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ChargeMagnitude operator *(HalfLife left, CurrentMagnitude right) => (Duration)left * right; + + /// HalfLife * Current1D = Charge, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Charge operator *(HalfLife left, Current1D right) => (Duration)left * right; + + /// HalfLife * Speed = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator *(HalfLife left, Speed right) => (Duration)left * right; + + /// HalfLife * Velocity1D = Displacement1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement1D operator *(HalfLife left, Velocity1D right) => (Duration)left * right; + + /// HalfLife * Velocity2D = Displacement2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement2D operator *(HalfLife left, Velocity2D right) => (Duration)left * right; + + /// HalfLife * Velocity3D = Displacement3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement3D operator *(HalfLife left, Velocity3D right) => (Duration)left * right; + + /// HalfLife * Velocity4D = Displacement4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement4D operator *(HalfLife left, Velocity4D right) => (Duration)left * right; + + /// HalfLife * AccelerationMagnitude = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(HalfLife left, AccelerationMagnitude right) => (Duration)left * right; + + /// HalfLife * Acceleration1D = Velocity1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity1D operator *(HalfLife left, Acceleration1D right) => (Duration)left * right; + + /// HalfLife * Acceleration2D = Velocity2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity2D operator *(HalfLife left, Acceleration2D right) => (Duration)left * right; + + /// HalfLife * Acceleration3D = Velocity3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity3D operator *(HalfLife left, Acceleration3D right) => (Duration)left * right; + + /// HalfLife * Acceleration4D = Velocity4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity4D operator *(HalfLife left, Acceleration4D right) => (Duration)left * right; + + /// HalfLife * JerkMagnitude = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator *(HalfLife left, JerkMagnitude right) => (Duration)left * right; + + /// HalfLife * Jerk1D = Acceleration1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration1D operator *(HalfLife left, Jerk1D right) => (Duration)left * right; + + /// HalfLife * Jerk2D = Acceleration2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration2D operator *(HalfLife left, Jerk2D right) => (Duration)left * right; + + /// HalfLife * Jerk3D = Acceleration3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration3D operator *(HalfLife left, Jerk3D right) => (Duration)left * right; + + /// HalfLife * Jerk4D = Acceleration4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration4D operator *(HalfLife left, Jerk4D right) => (Duration)left * right; + + /// HalfLife * SnapMagnitude = JerkMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static JerkMagnitude operator *(HalfLife left, SnapMagnitude right) => (Duration)left * right; + + /// HalfLife * Snap1D = Jerk1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk1D operator *(HalfLife left, Snap1D right) => (Duration)left * right; + + /// HalfLife * Snap2D = Jerk2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk2D operator *(HalfLife left, Snap2D right) => (Duration)left * right; + + /// HalfLife * Snap3D = Jerk3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk3D operator *(HalfLife left, Snap3D right) => (Duration)left * right; + + /// HalfLife * Snap4D = Jerk4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk4D operator *(HalfLife left, Snap4D right) => (Duration)left * right; + + /// HalfLife * Frequency = Ratio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Ratio operator *(HalfLife left, Frequency right) => (Duration)left * right; + + /// HalfLife * AngularSpeed = Angle, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Angle operator *(HalfLife left, AngularSpeed right) => (Duration)left * right; + + /// HalfLife * AngularVelocity1D = SignedAngle, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SignedAngle operator *(HalfLife left, AngularVelocity1D right) => (Duration)left * right; + + /// HalfLife * AngularVelocity3D = AngularDisplacement3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularDisplacement3D operator *(HalfLife left, AngularVelocity3D right) => (Duration)left * right; + + /// HalfLife * AngularAccelerationMagnitude = AngularSpeed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularSpeed operator *(HalfLife left, AngularAccelerationMagnitude right) => (Duration)left * right; + + /// HalfLife * AngularAcceleration1D = AngularVelocity1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularVelocity1D operator *(HalfLife left, AngularAcceleration1D right) => (Duration)left * right; + + /// HalfLife * AngularAcceleration3D = AngularVelocity3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularVelocity3D operator *(HalfLife left, AngularAcceleration3D right) => (Duration)left * right; + + /// HalfLife * AngularJerkMagnitude = AngularAccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularAccelerationMagnitude operator *(HalfLife left, AngularJerkMagnitude right) => (Duration)left * right; + + /// HalfLife * AngularJerk1D = AngularAcceleration1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularAcceleration1D operator *(HalfLife left, AngularJerk1D right) => (Duration)left * right; + + /// HalfLife * AngularJerk3D = AngularAcceleration3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularAcceleration3D operator *(HalfLife left, AngularJerk3D right) => (Duration)left * right; + + /// HalfLife * TorqueMagnitude = AngularMomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularMomentumMagnitude operator *(HalfLife left, TorqueMagnitude right) => (Duration)left * right; + + /// HalfLife * Torque1D = AngularMomentum1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularMomentum1D operator *(HalfLife left, Torque1D right) => (Duration)left * right; + + /// HalfLife * Torque3D = AngularMomentum3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularMomentum3D operator *(HalfLife left, Torque3D right) => (Duration)left * right; + + /// HalfLife * ForceMagnitude = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(HalfLife left, ForceMagnitude right) => (Duration)left * right; + + /// HalfLife * Force1D = Momentum1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum1D operator *(HalfLife left, Force1D right) => (Duration)left * right; + + /// HalfLife * Force2D = Momentum2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum2D operator *(HalfLife left, Force2D right) => (Duration)left * right; + + /// HalfLife * Force3D = Momentum3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum3D operator *(HalfLife left, Force3D right) => (Duration)left * right; + + /// HalfLife * Force4D = Momentum4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum4D operator *(HalfLife left, Force4D right) => (Duration)left * right; + + /// HalfLife * Power = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(HalfLife left, Power right) => (Duration)left * right; + + /// HalfLife * VolumetricFlowRate = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator *(HalfLife left, VolumetricFlowRate right) => (Duration)left * right; + + /// HalfLife * MassFlowRate = Mass, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Mass operator *(HalfLife left, MassFlowRate right) => (Duration)left * right; + + /// HalfLife * CatalyticActivity = AmountOfSubstance, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AmountOfSubstance operator *(HalfLife left, CatalyticActivity right) => (Duration)left * right; + + /// HalfLife * ReactionRate = Concentration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Concentration operator *(HalfLife left, ReactionRate right) => (Duration)left * right; + + /// HalfLife * VoltageMagnitude = MagneticFlux, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MagneticFlux operator *(HalfLife left, VoltageMagnitude right) => (Duration)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Heading.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Heading.g.cs index 2b71481b..2df194c8 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Heading.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Heading.g.cs @@ -149,5 +149,9 @@ namespace ktsu.Semantics.Quantities; /// Creates a Heading from a SignedAngle value. public static Heading From(SignedAngle value) => Create(value.Value); + + /// Heading / Duration = AngularVelocity1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularVelocity1D operator /(Heading left, Duration right) => (SignedAngle)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Heat.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Heat.g.cs index 4089fa64..f5581828 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Heat.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Heat.g.cs @@ -182,5 +182,45 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Heat values, returning the absolute difference as a non-negative Heat. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Heat operator -(Heat left, Heat right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Heat / Length = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator /(Heat left, Length right) => (Energy)left / right; + + /// Heat / ForceMagnitude = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(Heat left, ForceMagnitude right) => (Energy)left / right; + + /// Heat / Volume = Pressure, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Pressure operator /(Heat left, Volume right) => (Energy)left / right; + + /// Heat / Pressure = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator /(Heat left, Pressure right) => (Energy)left / right; + + /// Heat / Duration = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator /(Heat left, Duration right) => (Energy)left / right; + + /// Heat / Power = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(Heat left, Power right) => (Energy)left / right; + + /// Heat / Temperature = Entropy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Entropy operator /(Heat left, Temperature right) => (Energy)left / right; + + /// Heat / Entropy = Temperature, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Temperature operator /(Heat left, Entropy right) => (Energy)left / right; + + /// Heat / AmountOfSubstance = MolarEnergy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MolarEnergy operator /(Heat left, AmountOfSubstance right) => (Energy)left / right; + + /// Heat / MolarEnergy = AmountOfSubstance, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AmountOfSubstance operator /(Heat left, MolarEnergy right) => (Energy)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HeatCapacity.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HeatCapacity.g.cs index 0e2ddf0d..67fbdd11 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HeatCapacity.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HeatCapacity.g.cs @@ -118,5 +118,17 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two HeatCapacity values, returning the absolute difference as a non-negative HeatCapacity. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static HeatCapacity operator -(HeatCapacity left, HeatCapacity right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// HeatCapacity * Temperature = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(HeatCapacity left, Temperature right) => (Entropy)left * right; + + /// HeatCapacity / Mass = SpecificHeat, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SpecificHeat operator /(HeatCapacity left, Mass right) => (Entropy)left / right; + + /// HeatCapacity / SpecificHeat = Mass, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Mass operator /(HeatCapacity left, SpecificHeat right) => (Entropy)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HeatFlowRate.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HeatFlowRate.g.cs index a7686c86..02a2bab1 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HeatFlowRate.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HeatFlowRate.g.cs @@ -142,5 +142,41 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two HeatFlowRate values, returning the absolute difference as a non-negative HeatFlowRate. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static HeatFlowRate operator -(HeatFlowRate left, HeatFlowRate right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// HeatFlowRate / VoltageMagnitude = CurrentMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static CurrentMagnitude operator /(HeatFlowRate left, VoltageMagnitude right) => (Power)left / right; + + /// HeatFlowRate / CurrentMagnitude = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator /(HeatFlowRate left, CurrentMagnitude right) => (Power)left / right; + + /// HeatFlowRate / Speed = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator /(HeatFlowRate left, Speed right) => (Power)left / right; + + /// HeatFlowRate / ForceMagnitude = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator /(HeatFlowRate left, ForceMagnitude right) => (Power)left / right; + + /// HeatFlowRate * Duration = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(HeatFlowRate left, Duration right) => (Power)left * right; + + /// HeatFlowRate / Area = Irradiance, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Irradiance operator /(HeatFlowRate left, Area right) => (Power)left / right; + + /// HeatFlowRate / Irradiance = Area, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Area operator /(HeatFlowRate left, Irradiance right) => (Power)left / right; + + /// HeatFlowRate / Volume = ElectricPowerDensity, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ElectricPowerDensity operator /(HeatFlowRate left, Volume right) => (Power)left / right; + + /// HeatFlowRate / ElectricPowerDensity = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator /(HeatFlowRate left, ElectricPowerDensity right) => (Power)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HeatFlux.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HeatFlux.g.cs index 13e91bc8..7092a019 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HeatFlux.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/HeatFlux.g.cs @@ -118,5 +118,9 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two HeatFlux values, returning the absolute difference as a non-negative HeatFlux. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static HeatFlux operator -(HeatFlux left, HeatFlux right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// HeatFlux * Area = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(HeatFlux left, Area right) => (Irradiance)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Height.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Height.g.cs index 87914521..1f2038cc 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Height.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Height.g.cs @@ -206,5 +206,45 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Height values, returning the absolute difference as a non-negative Height. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Height operator -(Height left, Height right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Height * Length = Area, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Area operator *(Height left, Length right) => (Length)left * right; + + /// Height * Area = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator *(Height left, Area right) => (Length)left * right; + + /// Height / Duration = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator /(Height left, Duration right) => (Length)left / right; + + /// Height / Speed = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(Height left, Speed right) => (Length)left / right; + + /// Height * Frequency = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(Height left, Frequency right) => (Length)left * right; + + /// Height * ForceMagnitude = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Height left, ForceMagnitude right) => (Length)left * right; + + /// Height * ElectricFieldMagnitude = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator *(Height left, ElectricFieldMagnitude right) => (Length)left * right; + + /// Height * ElectricField1D = Voltage, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Voltage operator *(Height left, ElectricField1D right) => (Length)left * right; + + /// Height * SurfaceTension = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(Height left, SurfaceTension right) => (Length)left * right; + + /// Height * SpecificEnergyMagnitude = GravitationalParameter, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static GravitationalParameter operator *(Height left, SpecificEnergyMagnitude right) => (Length)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Impedance.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Impedance.g.cs index 752715f4..0f55417c 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Impedance.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Impedance.g.cs @@ -134,5 +134,13 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Impedance values, returning the absolute difference as a non-negative Impedance. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Impedance operator -(Impedance left, Impedance right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Impedance * CurrentMagnitude = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator *(Impedance left, CurrentMagnitude right) => (Resistance)left * right; + + /// Impedance * Current1D = Voltage, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Voltage operator *(Impedance left, Current1D right) => (Resistance)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/KineticEnergy.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/KineticEnergy.g.cs index a6e06f84..fbcf7daa 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/KineticEnergy.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/KineticEnergy.g.cs @@ -182,5 +182,45 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two KineticEnergy values, returning the absolute difference as a non-negative KineticEnergy. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static KineticEnergy operator -(KineticEnergy left, KineticEnergy right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// KineticEnergy / Length = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator /(KineticEnergy left, Length right) => (Energy)left / right; + + /// KineticEnergy / ForceMagnitude = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(KineticEnergy left, ForceMagnitude right) => (Energy)left / right; + + /// KineticEnergy / Volume = Pressure, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Pressure operator /(KineticEnergy left, Volume right) => (Energy)left / right; + + /// KineticEnergy / Pressure = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator /(KineticEnergy left, Pressure right) => (Energy)left / right; + + /// KineticEnergy / Duration = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator /(KineticEnergy left, Duration right) => (Energy)left / right; + + /// KineticEnergy / Power = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(KineticEnergy left, Power right) => (Energy)left / right; + + /// KineticEnergy / Temperature = Entropy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Entropy operator /(KineticEnergy left, Temperature right) => (Energy)left / right; + + /// KineticEnergy / Entropy = Temperature, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Temperature operator /(KineticEnergy left, Entropy right) => (Energy)left / right; + + /// KineticEnergy / AmountOfSubstance = MolarEnergy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MolarEnergy operator /(KineticEnergy left, AmountOfSubstance right) => (Energy)left / right; + + /// KineticEnergy / MolarEnergy = AmountOfSubstance, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AmountOfSubstance operator /(KineticEnergy left, MolarEnergy right) => (Energy)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Latency.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Latency.g.cs index f5940e85..e5a39d6f 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Latency.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Latency.g.cs @@ -182,5 +182,189 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Latency values, returning the absolute difference as a non-negative Latency. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Latency operator -(Latency left, Latency right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Latency * CurrentMagnitude = ChargeMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ChargeMagnitude operator *(Latency left, CurrentMagnitude right) => (Duration)left * right; + + /// Latency * Current1D = Charge, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Charge operator *(Latency left, Current1D right) => (Duration)left * right; + + /// Latency * Speed = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator *(Latency left, Speed right) => (Duration)left * right; + + /// Latency * Velocity1D = Displacement1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement1D operator *(Latency left, Velocity1D right) => (Duration)left * right; + + /// Latency * Velocity2D = Displacement2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement2D operator *(Latency left, Velocity2D right) => (Duration)left * right; + + /// Latency * Velocity3D = Displacement3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement3D operator *(Latency left, Velocity3D right) => (Duration)left * right; + + /// Latency * Velocity4D = Displacement4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement4D operator *(Latency left, Velocity4D right) => (Duration)left * right; + + /// Latency * AccelerationMagnitude = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(Latency left, AccelerationMagnitude right) => (Duration)left * right; + + /// Latency * Acceleration1D = Velocity1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity1D operator *(Latency left, Acceleration1D right) => (Duration)left * right; + + /// Latency * Acceleration2D = Velocity2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity2D operator *(Latency left, Acceleration2D right) => (Duration)left * right; + + /// Latency * Acceleration3D = Velocity3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity3D operator *(Latency left, Acceleration3D right) => (Duration)left * right; + + /// Latency * Acceleration4D = Velocity4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity4D operator *(Latency left, Acceleration4D right) => (Duration)left * right; + + /// Latency * JerkMagnitude = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator *(Latency left, JerkMagnitude right) => (Duration)left * right; + + /// Latency * Jerk1D = Acceleration1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration1D operator *(Latency left, Jerk1D right) => (Duration)left * right; + + /// Latency * Jerk2D = Acceleration2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration2D operator *(Latency left, Jerk2D right) => (Duration)left * right; + + /// Latency * Jerk3D = Acceleration3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration3D operator *(Latency left, Jerk3D right) => (Duration)left * right; + + /// Latency * Jerk4D = Acceleration4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration4D operator *(Latency left, Jerk4D right) => (Duration)left * right; + + /// Latency * SnapMagnitude = JerkMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static JerkMagnitude operator *(Latency left, SnapMagnitude right) => (Duration)left * right; + + /// Latency * Snap1D = Jerk1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk1D operator *(Latency left, Snap1D right) => (Duration)left * right; + + /// Latency * Snap2D = Jerk2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk2D operator *(Latency left, Snap2D right) => (Duration)left * right; + + /// Latency * Snap3D = Jerk3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk3D operator *(Latency left, Snap3D right) => (Duration)left * right; + + /// Latency * Snap4D = Jerk4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk4D operator *(Latency left, Snap4D right) => (Duration)left * right; + + /// Latency * Frequency = Ratio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Ratio operator *(Latency left, Frequency right) => (Duration)left * right; + + /// Latency * AngularSpeed = Angle, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Angle operator *(Latency left, AngularSpeed right) => (Duration)left * right; + + /// Latency * AngularVelocity1D = SignedAngle, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SignedAngle operator *(Latency left, AngularVelocity1D right) => (Duration)left * right; + + /// Latency * AngularVelocity3D = AngularDisplacement3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularDisplacement3D operator *(Latency left, AngularVelocity3D right) => (Duration)left * right; + + /// Latency * AngularAccelerationMagnitude = AngularSpeed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularSpeed operator *(Latency left, AngularAccelerationMagnitude right) => (Duration)left * right; + + /// Latency * AngularAcceleration1D = AngularVelocity1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularVelocity1D operator *(Latency left, AngularAcceleration1D right) => (Duration)left * right; + + /// Latency * AngularAcceleration3D = AngularVelocity3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularVelocity3D operator *(Latency left, AngularAcceleration3D right) => (Duration)left * right; + + /// Latency * AngularJerkMagnitude = AngularAccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularAccelerationMagnitude operator *(Latency left, AngularJerkMagnitude right) => (Duration)left * right; + + /// Latency * AngularJerk1D = AngularAcceleration1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularAcceleration1D operator *(Latency left, AngularJerk1D right) => (Duration)left * right; + + /// Latency * AngularJerk3D = AngularAcceleration3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularAcceleration3D operator *(Latency left, AngularJerk3D right) => (Duration)left * right; + + /// Latency * TorqueMagnitude = AngularMomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularMomentumMagnitude operator *(Latency left, TorqueMagnitude right) => (Duration)left * right; + + /// Latency * Torque1D = AngularMomentum1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularMomentum1D operator *(Latency left, Torque1D right) => (Duration)left * right; + + /// Latency * Torque3D = AngularMomentum3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularMomentum3D operator *(Latency left, Torque3D right) => (Duration)left * right; + + /// Latency * ForceMagnitude = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(Latency left, ForceMagnitude right) => (Duration)left * right; + + /// Latency * Force1D = Momentum1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum1D operator *(Latency left, Force1D right) => (Duration)left * right; + + /// Latency * Force2D = Momentum2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum2D operator *(Latency left, Force2D right) => (Duration)left * right; + + /// Latency * Force3D = Momentum3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum3D operator *(Latency left, Force3D right) => (Duration)left * right; + + /// Latency * Force4D = Momentum4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum4D operator *(Latency left, Force4D right) => (Duration)left * right; + + /// Latency * Power = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Latency left, Power right) => (Duration)left * right; + + /// Latency * VolumetricFlowRate = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator *(Latency left, VolumetricFlowRate right) => (Duration)left * right; + + /// Latency * MassFlowRate = Mass, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Mass operator *(Latency left, MassFlowRate right) => (Duration)left * right; + + /// Latency * CatalyticActivity = AmountOfSubstance, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AmountOfSubstance operator *(Latency left, CatalyticActivity right) => (Duration)left * right; + + /// Latency * ReactionRate = Concentration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Concentration operator *(Latency left, ReactionRate right) => (Duration)left * right; + + /// Latency * VoltageMagnitude = MagneticFlux, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MagneticFlux operator *(Latency left, VoltageMagnitude right) => (Duration)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Lift.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Lift.g.cs index 46aa4a36..d9731faa 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Lift.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Lift.g.cs @@ -142,5 +142,37 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Lift values, returning the absolute difference as a non-negative Lift. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Lift operator -(Lift left, Lift right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Lift / AccelerationMagnitude = Mass, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Mass operator /(Lift left, AccelerationMagnitude right) => (ForceMagnitude)left / right; + + /// Lift / Mass = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator /(Lift left, Mass right) => (ForceMagnitude)left / right; + + /// Lift * Length = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Lift left, Length right) => (ForceMagnitude)left * right; + + /// Lift * Duration = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(Lift left, Duration right) => (ForceMagnitude)left * right; + + /// Lift * Speed = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(Lift left, Speed right) => (ForceMagnitude)left * right; + + /// Lift / Area = Pressure, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Pressure operator /(Lift left, Area right) => (ForceMagnitude)left / right; + + /// Lift / Length = SurfaceTension, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SurfaceTension operator /(Lift left, Length right) => (ForceMagnitude)left / right; + + /// Lift / SurfaceTension = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(Lift left, SurfaceTension right) => (ForceMagnitude)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MachNumber.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MachNumber.g.cs index 8e4f5396..816efbe0 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MachNumber.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MachNumber.g.cs @@ -190,5 +190,29 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two MachNumber values, returning the absolute difference as a non-negative MachNumber. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static MachNumber operator -(MachNumber left, MachNumber right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// MachNumber * Ratio = Ratio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Ratio operator *(MachNumber left, Ratio right) => (Ratio)left * right; + + /// MachNumber * SignedRatio = SignedRatio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SignedRatio operator *(MachNumber left, SignedRatio right) => (Ratio)left * right; + + /// MachNumber / Duration = Frequency, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Frequency operator /(MachNumber left, Duration right) => (Ratio)left / right; + + /// MachNumber / Frequency = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(MachNumber left, Frequency right) => (Ratio)left / right; + + /// MachNumber / Temperature = ThermalExpansionCoefficient, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ThermalExpansionCoefficient operator /(MachNumber left, Temperature right) => (Ratio)left / right; + + /// MachNumber / ThermalExpansionCoefficient = Temperature, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Temperature operator /(MachNumber left, ThermalExpansionCoefficient right) => (Ratio)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MolarEnthalpy.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MolarEnthalpy.g.cs index babe0b52..575ae108 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MolarEnthalpy.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/MolarEnthalpy.g.cs @@ -134,5 +134,9 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two MolarEnthalpy values, returning the absolute difference as a non-negative MolarEnthalpy. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static MolarEnthalpy operator -(MolarEnthalpy left, MolarEnthalpy right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// MolarEnthalpy * AmountOfSubstance = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(MolarEnthalpy left, AmountOfSubstance right) => (MolarEnergy)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/NoiseReductionCoefficient.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/NoiseReductionCoefficient.g.cs index 125829ff..6776ba92 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/NoiseReductionCoefficient.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/NoiseReductionCoefficient.g.cs @@ -190,5 +190,29 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two NoiseReductionCoefficient values, returning the absolute difference as a non-negative NoiseReductionCoefficient. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static NoiseReductionCoefficient operator -(NoiseReductionCoefficient left, NoiseReductionCoefficient right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// NoiseReductionCoefficient * Ratio = Ratio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Ratio operator *(NoiseReductionCoefficient left, Ratio right) => (Ratio)left * right; + + /// NoiseReductionCoefficient * SignedRatio = SignedRatio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SignedRatio operator *(NoiseReductionCoefficient left, SignedRatio right) => (Ratio)left * right; + + /// NoiseReductionCoefficient / Duration = Frequency, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Frequency operator /(NoiseReductionCoefficient left, Duration right) => (Ratio)left / right; + + /// NoiseReductionCoefficient / Frequency = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(NoiseReductionCoefficient left, Frequency right) => (Ratio)left / right; + + /// NoiseReductionCoefficient / Temperature = ThermalExpansionCoefficient, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ThermalExpansionCoefficient operator /(NoiseReductionCoefficient left, Temperature right) => (Ratio)left / right; + + /// NoiseReductionCoefficient / ThermalExpansionCoefficient = Temperature, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Temperature operator /(NoiseReductionCoefficient left, ThermalExpansionCoefficient right) => (Ratio)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/NormalForce.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/NormalForce.g.cs index 8de8ed84..8d59c894 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/NormalForce.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/NormalForce.g.cs @@ -142,5 +142,37 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two NormalForce values, returning the absolute difference as a non-negative NormalForce. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static NormalForce operator -(NormalForce left, NormalForce right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// NormalForce / AccelerationMagnitude = Mass, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Mass operator /(NormalForce left, AccelerationMagnitude right) => (ForceMagnitude)left / right; + + /// NormalForce / Mass = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator /(NormalForce left, Mass right) => (ForceMagnitude)left / right; + + /// NormalForce * Length = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(NormalForce left, Length right) => (ForceMagnitude)left * right; + + /// NormalForce * Duration = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(NormalForce left, Duration right) => (ForceMagnitude)left * right; + + /// NormalForce * Speed = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(NormalForce left, Speed right) => (ForceMagnitude)left * right; + + /// NormalForce / Area = Pressure, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Pressure operator /(NormalForce left, Area right) => (ForceMagnitude)left / right; + + /// NormalForce / Length = SurfaceTension, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SurfaceTension operator /(NormalForce left, Length right) => (ForceMagnitude)left / right; + + /// NormalForce / SurfaceTension = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(NormalForce left, SurfaceTension right) => (ForceMagnitude)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Offset.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Offset.g.cs index fc00a0bf..395e4fc2 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Offset.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Offset.g.cs @@ -198,5 +198,9 @@ namespace ktsu.Semantics.Quantities; /// Creates a Offset from a Displacement1D value. public static Offset From(Displacement1D value) => Create(value.Value); + + /// Offset / Duration = Velocity1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity1D operator /(Offset left, Duration right) => (Displacement1D)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Perimeter.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Perimeter.g.cs index 0966914a..af9f17be 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Perimeter.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Perimeter.g.cs @@ -206,5 +206,45 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Perimeter values, returning the absolute difference as a non-negative Perimeter. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Perimeter operator -(Perimeter left, Perimeter right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Perimeter * Length = Area, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Area operator *(Perimeter left, Length right) => (Length)left * right; + + /// Perimeter * Area = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator *(Perimeter left, Area right) => (Length)left * right; + + /// Perimeter / Duration = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator /(Perimeter left, Duration right) => (Length)left / right; + + /// Perimeter / Speed = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(Perimeter left, Speed right) => (Length)left / right; + + /// Perimeter * Frequency = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(Perimeter left, Frequency right) => (Length)left * right; + + /// Perimeter * ForceMagnitude = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Perimeter left, ForceMagnitude right) => (Length)left * right; + + /// Perimeter * ElectricFieldMagnitude = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator *(Perimeter left, ElectricFieldMagnitude right) => (Length)left * right; + + /// Perimeter * ElectricField1D = Voltage, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Voltage operator *(Perimeter left, ElectricField1D right) => (Length)left * right; + + /// Perimeter * SurfaceTension = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(Perimeter left, SurfaceTension right) => (Length)left * right; + + /// Perimeter * SpecificEnergyMagnitude = GravitationalParameter, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static GravitationalParameter operator *(Perimeter left, SpecificEnergyMagnitude right) => (Length)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Period.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Period.g.cs index 2e3305bc..ee5733c8 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Period.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Period.g.cs @@ -182,5 +182,189 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Period values, returning the absolute difference as a positive Period. Throws when the two are equal, since a Period cannot be zero; widen to first for a difference that may be. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Period operator -(Period left, Period right) => Create(Vector0Guards.EnsurePositive(T.Abs(left.Quantity - right.Quantity), nameof(right))); + + /// Period * CurrentMagnitude = ChargeMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ChargeMagnitude operator *(Period left, CurrentMagnitude right) => (Duration)left * right; + + /// Period * Current1D = Charge, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Charge operator *(Period left, Current1D right) => (Duration)left * right; + + /// Period * Speed = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator *(Period left, Speed right) => (Duration)left * right; + + /// Period * Velocity1D = Displacement1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement1D operator *(Period left, Velocity1D right) => (Duration)left * right; + + /// Period * Velocity2D = Displacement2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement2D operator *(Period left, Velocity2D right) => (Duration)left * right; + + /// Period * Velocity3D = Displacement3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement3D operator *(Period left, Velocity3D right) => (Duration)left * right; + + /// Period * Velocity4D = Displacement4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement4D operator *(Period left, Velocity4D right) => (Duration)left * right; + + /// Period * AccelerationMagnitude = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(Period left, AccelerationMagnitude right) => (Duration)left * right; + + /// Period * Acceleration1D = Velocity1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity1D operator *(Period left, Acceleration1D right) => (Duration)left * right; + + /// Period * Acceleration2D = Velocity2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity2D operator *(Period left, Acceleration2D right) => (Duration)left * right; + + /// Period * Acceleration3D = Velocity3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity3D operator *(Period left, Acceleration3D right) => (Duration)left * right; + + /// Period * Acceleration4D = Velocity4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity4D operator *(Period left, Acceleration4D right) => (Duration)left * right; + + /// Period * JerkMagnitude = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator *(Period left, JerkMagnitude right) => (Duration)left * right; + + /// Period * Jerk1D = Acceleration1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration1D operator *(Period left, Jerk1D right) => (Duration)left * right; + + /// Period * Jerk2D = Acceleration2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration2D operator *(Period left, Jerk2D right) => (Duration)left * right; + + /// Period * Jerk3D = Acceleration3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration3D operator *(Period left, Jerk3D right) => (Duration)left * right; + + /// Period * Jerk4D = Acceleration4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration4D operator *(Period left, Jerk4D right) => (Duration)left * right; + + /// Period * SnapMagnitude = JerkMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static JerkMagnitude operator *(Period left, SnapMagnitude right) => (Duration)left * right; + + /// Period * Snap1D = Jerk1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk1D operator *(Period left, Snap1D right) => (Duration)left * right; + + /// Period * Snap2D = Jerk2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk2D operator *(Period left, Snap2D right) => (Duration)left * right; + + /// Period * Snap3D = Jerk3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk3D operator *(Period left, Snap3D right) => (Duration)left * right; + + /// Period * Snap4D = Jerk4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk4D operator *(Period left, Snap4D right) => (Duration)left * right; + + /// Period * Frequency = Ratio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Ratio operator *(Period left, Frequency right) => (Duration)left * right; + + /// Period * AngularSpeed = Angle, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Angle operator *(Period left, AngularSpeed right) => (Duration)left * right; + + /// Period * AngularVelocity1D = SignedAngle, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SignedAngle operator *(Period left, AngularVelocity1D right) => (Duration)left * right; + + /// Period * AngularVelocity3D = AngularDisplacement3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularDisplacement3D operator *(Period left, AngularVelocity3D right) => (Duration)left * right; + + /// Period * AngularAccelerationMagnitude = AngularSpeed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularSpeed operator *(Period left, AngularAccelerationMagnitude right) => (Duration)left * right; + + /// Period * AngularAcceleration1D = AngularVelocity1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularVelocity1D operator *(Period left, AngularAcceleration1D right) => (Duration)left * right; + + /// Period * AngularAcceleration3D = AngularVelocity3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularVelocity3D operator *(Period left, AngularAcceleration3D right) => (Duration)left * right; + + /// Period * AngularJerkMagnitude = AngularAccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularAccelerationMagnitude operator *(Period left, AngularJerkMagnitude right) => (Duration)left * right; + + /// Period * AngularJerk1D = AngularAcceleration1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularAcceleration1D operator *(Period left, AngularJerk1D right) => (Duration)left * right; + + /// Period * AngularJerk3D = AngularAcceleration3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularAcceleration3D operator *(Period left, AngularJerk3D right) => (Duration)left * right; + + /// Period * TorqueMagnitude = AngularMomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularMomentumMagnitude operator *(Period left, TorqueMagnitude right) => (Duration)left * right; + + /// Period * Torque1D = AngularMomentum1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularMomentum1D operator *(Period left, Torque1D right) => (Duration)left * right; + + /// Period * Torque3D = AngularMomentum3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularMomentum3D operator *(Period left, Torque3D right) => (Duration)left * right; + + /// Period * ForceMagnitude = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(Period left, ForceMagnitude right) => (Duration)left * right; + + /// Period * Force1D = Momentum1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum1D operator *(Period left, Force1D right) => (Duration)left * right; + + /// Period * Force2D = Momentum2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum2D operator *(Period left, Force2D right) => (Duration)left * right; + + /// Period * Force3D = Momentum3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum3D operator *(Period left, Force3D right) => (Duration)left * right; + + /// Period * Force4D = Momentum4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum4D operator *(Period left, Force4D right) => (Duration)left * right; + + /// Period * Power = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Period left, Power right) => (Duration)left * right; + + /// Period * VolumetricFlowRate = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator *(Period left, VolumetricFlowRate right) => (Duration)left * right; + + /// Period * MassFlowRate = Mass, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Mass operator *(Period left, MassFlowRate right) => (Duration)left * right; + + /// Period * CatalyticActivity = AmountOfSubstance, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AmountOfSubstance operator *(Period left, CatalyticActivity right) => (Duration)left * right; + + /// Period * ReactionRate = Concentration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Concentration operator *(Period left, ReactionRate right) => (Duration)left * right; + + /// Period * VoltageMagnitude = MagneticFlux, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MagneticFlux operator *(Period left, VoltageMagnitude right) => (Duration)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Phase.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Phase.g.cs index 7d5ce60a..f58e5b14 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Phase.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Phase.g.cs @@ -149,5 +149,9 @@ namespace ktsu.Semantics.Quantities; /// Creates a Phase from a SignedAngle value. public static Phase From(SignedAngle value) => Create(value.Value); + + /// Phase / Duration = AngularVelocity1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularVelocity1D operator /(Phase left, Duration right) => (SignedAngle)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/PhaseVelocity.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/PhaseVelocity.g.cs index cb806777..ae16aa43 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/PhaseVelocity.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/PhaseVelocity.g.cs @@ -158,5 +158,33 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two PhaseVelocity values, returning the absolute difference as a non-negative PhaseVelocity. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static PhaseVelocity operator -(PhaseVelocity left, PhaseVelocity right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// PhaseVelocity * Mass = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(PhaseVelocity left, Mass right) => (Speed)left * right; + + /// PhaseVelocity * Duration = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator *(PhaseVelocity left, Duration right) => (Speed)left * right; + + /// PhaseVelocity / Duration = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator /(PhaseVelocity left, Duration right) => (Speed)left / right; + + /// PhaseVelocity / AccelerationMagnitude = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(PhaseVelocity left, AccelerationMagnitude right) => (Speed)left / right; + + /// PhaseVelocity / Length = Frequency, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Frequency operator /(PhaseVelocity left, Length right) => (Speed)left / right; + + /// PhaseVelocity / Frequency = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(PhaseVelocity left, Frequency right) => (Speed)left / right; + + /// PhaseVelocity * ForceMagnitude = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(PhaseVelocity left, ForceMagnitude right) => (Speed)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Pitch.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Pitch.g.cs index 4ccf93d4..02f913aa 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Pitch.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Pitch.g.cs @@ -134,5 +134,13 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Pitch values, returning the absolute difference as a non-negative Pitch. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Pitch operator -(Pitch left, Pitch right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Pitch * Duration = Ratio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Ratio operator *(Pitch left, Duration right) => (Frequency)left * right; + + /// Pitch * Length = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(Pitch left, Length right) => (Frequency)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Position3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Position3D.g.cs index b1c46c47..74301c6c 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Position3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Position3D.g.cs @@ -202,6 +202,9 @@ public Position3D Normalize() /// Negates a vector. public static Position3D operator -(Position3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; + /// Position3D / Duration = Velocity3D, through . + public static Velocity3D operator /(Position3D left, Duration right) => (Displacement3D)left / right; + /// Implicit conversion to Displacement3D. public static implicit operator Displacement3D(Position3D value) => new() { X = value.X, Y = value.Y, Z = value.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/PotentialEnergy.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/PotentialEnergy.g.cs index 6027bbb7..421c2729 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/PotentialEnergy.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/PotentialEnergy.g.cs @@ -182,5 +182,45 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two PotentialEnergy values, returning the absolute difference as a non-negative PotentialEnergy. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static PotentialEnergy operator -(PotentialEnergy left, PotentialEnergy right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// PotentialEnergy / Length = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator /(PotentialEnergy left, Length right) => (Energy)left / right; + + /// PotentialEnergy / ForceMagnitude = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(PotentialEnergy left, ForceMagnitude right) => (Energy)left / right; + + /// PotentialEnergy / Volume = Pressure, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Pressure operator /(PotentialEnergy left, Volume right) => (Energy)left / right; + + /// PotentialEnergy / Pressure = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator /(PotentialEnergy left, Pressure right) => (Energy)left / right; + + /// PotentialEnergy / Duration = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator /(PotentialEnergy left, Duration right) => (Energy)left / right; + + /// PotentialEnergy / Power = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(PotentialEnergy left, Power right) => (Energy)left / right; + + /// PotentialEnergy / Temperature = Entropy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Entropy operator /(PotentialEnergy left, Temperature right) => (Energy)left / right; + + /// PotentialEnergy / Entropy = Temperature, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Temperature operator /(PotentialEnergy left, Entropy right) => (Energy)left / right; + + /// PotentialEnergy / AmountOfSubstance = MolarEnergy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MolarEnergy operator /(PotentialEnergy left, AmountOfSubstance right) => (Energy)left / right; + + /// PotentialEnergy / MolarEnergy = AmountOfSubstance, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AmountOfSubstance operator /(PotentialEnergy left, MolarEnergy right) => (Energy)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Radius.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Radius.g.cs index 9fb9336a..ac6a3c1e 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Radius.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Radius.g.cs @@ -206,5 +206,45 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Radius values, returning the absolute difference as a non-negative Radius. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Radius operator -(Radius left, Radius right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Radius * Length = Area, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Area operator *(Radius left, Length right) => (Length)left * right; + + /// Radius * Area = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator *(Radius left, Area right) => (Length)left * right; + + /// Radius / Duration = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator /(Radius left, Duration right) => (Length)left / right; + + /// Radius / Speed = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(Radius left, Speed right) => (Length)left / right; + + /// Radius * Frequency = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(Radius left, Frequency right) => (Length)left * right; + + /// Radius * ForceMagnitude = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Radius left, ForceMagnitude right) => (Length)left * right; + + /// Radius * ElectricFieldMagnitude = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator *(Radius left, ElectricFieldMagnitude right) => (Length)left * right; + + /// Radius * ElectricField1D = Voltage, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Voltage operator *(Radius left, ElectricField1D right) => (Length)left * right; + + /// Radius * SurfaceTension = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(Radius left, SurfaceTension right) => (Length)left * right; + + /// Radius * SpecificEnergyMagnitude = GravitationalParameter, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static GravitationalParameter operator *(Radius left, SpecificEnergyMagnitude right) => (Length)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ReflectionCoefficient.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ReflectionCoefficient.g.cs index 961da948..a5972740 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ReflectionCoefficient.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ReflectionCoefficient.g.cs @@ -184,5 +184,13 @@ namespace ktsu.Semantics.Quantities; /// Creates a ReflectionCoefficient from a SignedRatio value. public static ReflectionCoefficient From(SignedRatio value) => Create(value.Value); + + /// ReflectionCoefficient * Ratio = SignedRatio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SignedRatio operator *(ReflectionCoefficient left, Ratio right) => (SignedRatio)left * right; + + /// ReflectionCoefficient / Ratio = SignedRatio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SignedRatio operator /(ReflectionCoefficient left, Ratio right) => (SignedRatio)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/RefractiveIndex.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/RefractiveIndex.g.cs index 56af640b..ca547845 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/RefractiveIndex.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/RefractiveIndex.g.cs @@ -190,5 +190,29 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two RefractiveIndex values, returning the absolute difference as a non-negative RefractiveIndex. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static RefractiveIndex operator -(RefractiveIndex left, RefractiveIndex right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// RefractiveIndex * Ratio = Ratio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Ratio operator *(RefractiveIndex left, Ratio right) => (Ratio)left * right; + + /// RefractiveIndex * SignedRatio = SignedRatio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SignedRatio operator *(RefractiveIndex left, SignedRatio right) => (Ratio)left * right; + + /// RefractiveIndex / Duration = Frequency, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Frequency operator /(RefractiveIndex left, Duration right) => (Ratio)left / right; + + /// RefractiveIndex / Frequency = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(RefractiveIndex left, Frequency right) => (Ratio)left / right; + + /// RefractiveIndex / Temperature = ThermalExpansionCoefficient, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ThermalExpansionCoefficient operator /(RefractiveIndex left, Temperature right) => (Ratio)left / right; + + /// RefractiveIndex / ThermalExpansionCoefficient = Temperature, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Temperature operator /(RefractiveIndex left, ThermalExpansionCoefficient right) => (Ratio)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ReverberationTime.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ReverberationTime.g.cs index df76f8b1..65d25c0f 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ReverberationTime.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ReverberationTime.g.cs @@ -182,5 +182,189 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two ReverberationTime values, returning the absolute difference as a non-negative ReverberationTime. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static ReverberationTime operator -(ReverberationTime left, ReverberationTime right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// ReverberationTime * CurrentMagnitude = ChargeMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ChargeMagnitude operator *(ReverberationTime left, CurrentMagnitude right) => (Duration)left * right; + + /// ReverberationTime * Current1D = Charge, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Charge operator *(ReverberationTime left, Current1D right) => (Duration)left * right; + + /// ReverberationTime * Speed = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator *(ReverberationTime left, Speed right) => (Duration)left * right; + + /// ReverberationTime * Velocity1D = Displacement1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement1D operator *(ReverberationTime left, Velocity1D right) => (Duration)left * right; + + /// ReverberationTime * Velocity2D = Displacement2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement2D operator *(ReverberationTime left, Velocity2D right) => (Duration)left * right; + + /// ReverberationTime * Velocity3D = Displacement3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement3D operator *(ReverberationTime left, Velocity3D right) => (Duration)left * right; + + /// ReverberationTime * Velocity4D = Displacement4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement4D operator *(ReverberationTime left, Velocity4D right) => (Duration)left * right; + + /// ReverberationTime * AccelerationMagnitude = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(ReverberationTime left, AccelerationMagnitude right) => (Duration)left * right; + + /// ReverberationTime * Acceleration1D = Velocity1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity1D operator *(ReverberationTime left, Acceleration1D right) => (Duration)left * right; + + /// ReverberationTime * Acceleration2D = Velocity2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity2D operator *(ReverberationTime left, Acceleration2D right) => (Duration)left * right; + + /// ReverberationTime * Acceleration3D = Velocity3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity3D operator *(ReverberationTime left, Acceleration3D right) => (Duration)left * right; + + /// ReverberationTime * Acceleration4D = Velocity4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity4D operator *(ReverberationTime left, Acceleration4D right) => (Duration)left * right; + + /// ReverberationTime * JerkMagnitude = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator *(ReverberationTime left, JerkMagnitude right) => (Duration)left * right; + + /// ReverberationTime * Jerk1D = Acceleration1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration1D operator *(ReverberationTime left, Jerk1D right) => (Duration)left * right; + + /// ReverberationTime * Jerk2D = Acceleration2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration2D operator *(ReverberationTime left, Jerk2D right) => (Duration)left * right; + + /// ReverberationTime * Jerk3D = Acceleration3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration3D operator *(ReverberationTime left, Jerk3D right) => (Duration)left * right; + + /// ReverberationTime * Jerk4D = Acceleration4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration4D operator *(ReverberationTime left, Jerk4D right) => (Duration)left * right; + + /// ReverberationTime * SnapMagnitude = JerkMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static JerkMagnitude operator *(ReverberationTime left, SnapMagnitude right) => (Duration)left * right; + + /// ReverberationTime * Snap1D = Jerk1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk1D operator *(ReverberationTime left, Snap1D right) => (Duration)left * right; + + /// ReverberationTime * Snap2D = Jerk2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk2D operator *(ReverberationTime left, Snap2D right) => (Duration)left * right; + + /// ReverberationTime * Snap3D = Jerk3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk3D operator *(ReverberationTime left, Snap3D right) => (Duration)left * right; + + /// ReverberationTime * Snap4D = Jerk4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk4D operator *(ReverberationTime left, Snap4D right) => (Duration)left * right; + + /// ReverberationTime * Frequency = Ratio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Ratio operator *(ReverberationTime left, Frequency right) => (Duration)left * right; + + /// ReverberationTime * AngularSpeed = Angle, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Angle operator *(ReverberationTime left, AngularSpeed right) => (Duration)left * right; + + /// ReverberationTime * AngularVelocity1D = SignedAngle, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SignedAngle operator *(ReverberationTime left, AngularVelocity1D right) => (Duration)left * right; + + /// ReverberationTime * AngularVelocity3D = AngularDisplacement3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularDisplacement3D operator *(ReverberationTime left, AngularVelocity3D right) => (Duration)left * right; + + /// ReverberationTime * AngularAccelerationMagnitude = AngularSpeed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularSpeed operator *(ReverberationTime left, AngularAccelerationMagnitude right) => (Duration)left * right; + + /// ReverberationTime * AngularAcceleration1D = AngularVelocity1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularVelocity1D operator *(ReverberationTime left, AngularAcceleration1D right) => (Duration)left * right; + + /// ReverberationTime * AngularAcceleration3D = AngularVelocity3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularVelocity3D operator *(ReverberationTime left, AngularAcceleration3D right) => (Duration)left * right; + + /// ReverberationTime * AngularJerkMagnitude = AngularAccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularAccelerationMagnitude operator *(ReverberationTime left, AngularJerkMagnitude right) => (Duration)left * right; + + /// ReverberationTime * AngularJerk1D = AngularAcceleration1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularAcceleration1D operator *(ReverberationTime left, AngularJerk1D right) => (Duration)left * right; + + /// ReverberationTime * AngularJerk3D = AngularAcceleration3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularAcceleration3D operator *(ReverberationTime left, AngularJerk3D right) => (Duration)left * right; + + /// ReverberationTime * TorqueMagnitude = AngularMomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularMomentumMagnitude operator *(ReverberationTime left, TorqueMagnitude right) => (Duration)left * right; + + /// ReverberationTime * Torque1D = AngularMomentum1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularMomentum1D operator *(ReverberationTime left, Torque1D right) => (Duration)left * right; + + /// ReverberationTime * Torque3D = AngularMomentum3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularMomentum3D operator *(ReverberationTime left, Torque3D right) => (Duration)left * right; + + /// ReverberationTime * ForceMagnitude = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(ReverberationTime left, ForceMagnitude right) => (Duration)left * right; + + /// ReverberationTime * Force1D = Momentum1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum1D operator *(ReverberationTime left, Force1D right) => (Duration)left * right; + + /// ReverberationTime * Force2D = Momentum2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum2D operator *(ReverberationTime left, Force2D right) => (Duration)left * right; + + /// ReverberationTime * Force3D = Momentum3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum3D operator *(ReverberationTime left, Force3D right) => (Duration)left * right; + + /// ReverberationTime * Force4D = Momentum4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum4D operator *(ReverberationTime left, Force4D right) => (Duration)left * right; + + /// ReverberationTime * Power = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(ReverberationTime left, Power right) => (Duration)left * right; + + /// ReverberationTime * VolumetricFlowRate = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator *(ReverberationTime left, VolumetricFlowRate right) => (Duration)left * right; + + /// ReverberationTime * MassFlowRate = Mass, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Mass operator *(ReverberationTime left, MassFlowRate right) => (Duration)left * right; + + /// ReverberationTime * CatalyticActivity = AmountOfSubstance, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AmountOfSubstance operator *(ReverberationTime left, CatalyticActivity right) => (Duration)left * right; + + /// ReverberationTime * ReactionRate = Concentration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Concentration operator *(ReverberationTime left, ReactionRate right) => (Duration)left * right; + + /// ReverberationTime * VoltageMagnitude = MagneticFlux, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MagneticFlux operator *(ReverberationTime left, VoltageMagnitude right) => (Duration)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ReynoldsNumber.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ReynoldsNumber.g.cs index 0243ff1a..62533d00 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ReynoldsNumber.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ReynoldsNumber.g.cs @@ -190,5 +190,29 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two ReynoldsNumber values, returning the absolute difference as a non-negative ReynoldsNumber. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static ReynoldsNumber operator -(ReynoldsNumber left, ReynoldsNumber right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// ReynoldsNumber * Ratio = Ratio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Ratio operator *(ReynoldsNumber left, Ratio right) => (Ratio)left * right; + + /// ReynoldsNumber * SignedRatio = SignedRatio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SignedRatio operator *(ReynoldsNumber left, SignedRatio right) => (Ratio)left * right; + + /// ReynoldsNumber / Duration = Frequency, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Frequency operator /(ReynoldsNumber left, Duration right) => (Ratio)left / right; + + /// ReynoldsNumber / Frequency = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(ReynoldsNumber left, Frequency right) => (Ratio)left / right; + + /// ReynoldsNumber / Temperature = ThermalExpansionCoefficient, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ThermalExpansionCoefficient operator /(ReynoldsNumber left, Temperature right) => (Ratio)left / right; + + /// ReynoldsNumber / ThermalExpansionCoefficient = Temperature, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Temperature operator /(ReynoldsNumber left, ThermalExpansionCoefficient right) => (Ratio)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Rotation.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Rotation.g.cs index 08911f0e..d2d5134c 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Rotation.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Rotation.g.cs @@ -149,5 +149,9 @@ namespace ktsu.Semantics.Quantities; /// Creates a Rotation from a SignedAngle value. public static Rotation From(SignedAngle value) => Create(value.Value); + + /// Rotation / Duration = AngularVelocity1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularVelocity1D operator /(Rotation left, Duration right) => (SignedAngle)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SamplingRate.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SamplingRate.g.cs index 579d505e..a5142e08 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SamplingRate.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SamplingRate.g.cs @@ -134,5 +134,13 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two SamplingRate values, returning the absolute difference as a non-negative SamplingRate. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static SamplingRate operator -(SamplingRate left, SamplingRate right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// SamplingRate * Duration = Ratio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Ratio operator *(SamplingRate left, Duration right) => (Frequency)left * right; + + /// SamplingRate * Length = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(SamplingRate left, Length right) => (Frequency)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ShearModulus.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ShearModulus.g.cs index 633f6986..969b7c6c 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ShearModulus.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ShearModulus.g.cs @@ -158,5 +158,17 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two ShearModulus values, returning the absolute difference as a non-negative ShearModulus. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static ShearModulus operator -(ShearModulus left, ShearModulus right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// ShearModulus * Area = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(ShearModulus left, Area right) => (Pressure)left * right; + + /// ShearModulus * Volume = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(ShearModulus left, Volume right) => (Pressure)left * right; + + /// ShearModulus * Sensitivity = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator *(ShearModulus left, Sensitivity right) => (Pressure)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundAbsorption.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundAbsorption.g.cs index e822d6bd..b9b989e2 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundAbsorption.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundAbsorption.g.cs @@ -190,5 +190,29 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two SoundAbsorption values, returning the absolute difference as a non-negative SoundAbsorption. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static SoundAbsorption operator -(SoundAbsorption left, SoundAbsorption right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// SoundAbsorption * Ratio = Ratio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Ratio operator *(SoundAbsorption left, Ratio right) => (Ratio)left * right; + + /// SoundAbsorption * SignedRatio = SignedRatio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SignedRatio operator *(SoundAbsorption left, SignedRatio right) => (Ratio)left * right; + + /// SoundAbsorption / Duration = Frequency, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Frequency operator /(SoundAbsorption left, Duration right) => (Ratio)left / right; + + /// SoundAbsorption / Frequency = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(SoundAbsorption left, Frequency right) => (Ratio)left / right; + + /// SoundAbsorption / Temperature = ThermalExpansionCoefficient, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ThermalExpansionCoefficient operator /(SoundAbsorption left, Temperature right) => (Ratio)left / right; + + /// SoundAbsorption / ThermalExpansionCoefficient = Temperature, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Temperature operator /(SoundAbsorption left, ThermalExpansionCoefficient right) => (Ratio)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundIntensity.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundIntensity.g.cs index 75bf0101..7e52033c 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundIntensity.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundIntensity.g.cs @@ -118,5 +118,9 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two SoundIntensity values, returning the absolute difference as a non-negative SoundIntensity. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static SoundIntensity operator -(SoundIntensity left, SoundIntensity right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// SoundIntensity * Area = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(SoundIntensity left, Area right) => (Irradiance)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundPower.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundPower.g.cs index 812140aa..be4ef4a8 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundPower.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundPower.g.cs @@ -142,5 +142,41 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two SoundPower values, returning the absolute difference as a non-negative SoundPower. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static SoundPower operator -(SoundPower left, SoundPower right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// SoundPower / VoltageMagnitude = CurrentMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static CurrentMagnitude operator /(SoundPower left, VoltageMagnitude right) => (Power)left / right; + + /// SoundPower / CurrentMagnitude = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator /(SoundPower left, CurrentMagnitude right) => (Power)left / right; + + /// SoundPower / Speed = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator /(SoundPower left, Speed right) => (Power)left / right; + + /// SoundPower / ForceMagnitude = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator /(SoundPower left, ForceMagnitude right) => (Power)left / right; + + /// SoundPower * Duration = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(SoundPower left, Duration right) => (Power)left * right; + + /// SoundPower / Area = Irradiance, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Irradiance operator /(SoundPower left, Area right) => (Power)left / right; + + /// SoundPower / Irradiance = Area, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Area operator /(SoundPower left, Irradiance right) => (Power)left / right; + + /// SoundPower / Volume = ElectricPowerDensity, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ElectricPowerDensity operator /(SoundPower left, Volume right) => (Power)left / right; + + /// SoundPower / ElectricPowerDensity = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator /(SoundPower left, ElectricPowerDensity right) => (Power)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundPressure.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundPressure.g.cs index 0a492731..bd40fe80 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundPressure.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundPressure.g.cs @@ -158,5 +158,17 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two SoundPressure values, returning the absolute difference as a non-negative SoundPressure. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static SoundPressure operator -(SoundPressure left, SoundPressure right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// SoundPressure * Area = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(SoundPressure left, Area right) => (Pressure)left * right; + + /// SoundPressure * Volume = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(SoundPressure left, Volume right) => (Pressure)left * right; + + /// SoundPressure * Sensitivity = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator *(SoundPressure left, Sensitivity right) => (Pressure)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundSpeed.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundSpeed.g.cs index d8ec17c3..9d21ef18 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundSpeed.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundSpeed.g.cs @@ -158,5 +158,33 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two SoundSpeed values, returning the absolute difference as a non-negative SoundSpeed. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static SoundSpeed operator -(SoundSpeed left, SoundSpeed right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// SoundSpeed * Mass = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(SoundSpeed left, Mass right) => (Speed)left * right; + + /// SoundSpeed * Duration = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator *(SoundSpeed left, Duration right) => (Speed)left * right; + + /// SoundSpeed / Duration = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator /(SoundSpeed left, Duration right) => (Speed)left / right; + + /// SoundSpeed / AccelerationMagnitude = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(SoundSpeed left, AccelerationMagnitude right) => (Speed)left / right; + + /// SoundSpeed / Length = Frequency, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Frequency operator /(SoundSpeed left, Length right) => (Speed)left / right; + + /// SoundSpeed / Frequency = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(SoundSpeed left, Frequency right) => (Speed)left / right; + + /// SoundSpeed * ForceMagnitude = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(SoundSpeed left, ForceMagnitude right) => (Speed)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundTransmissionClass.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundTransmissionClass.g.cs index 935cb853..4d81e650 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundTransmissionClass.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SoundTransmissionClass.g.cs @@ -190,5 +190,29 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two SoundTransmissionClass values, returning the absolute difference as a non-negative SoundTransmissionClass. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static SoundTransmissionClass operator -(SoundTransmissionClass left, SoundTransmissionClass right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// SoundTransmissionClass * Ratio = Ratio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Ratio operator *(SoundTransmissionClass left, Ratio right) => (Ratio)left * right; + + /// SoundTransmissionClass * SignedRatio = SignedRatio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SignedRatio operator *(SoundTransmissionClass left, SignedRatio right) => (Ratio)left * right; + + /// SoundTransmissionClass / Duration = Frequency, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Frequency operator /(SoundTransmissionClass left, Duration right) => (Ratio)left / right; + + /// SoundTransmissionClass / Frequency = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(SoundTransmissionClass left, Frequency right) => (Ratio)left / right; + + /// SoundTransmissionClass / Temperature = ThermalExpansionCoefficient, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ThermalExpansionCoefficient operator /(SoundTransmissionClass left, Temperature right) => (Ratio)left / right; + + /// SoundTransmissionClass / ThermalExpansionCoefficient = Temperature, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Temperature operator /(SoundTransmissionClass left, ThermalExpansionCoefficient right) => (Ratio)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificEntropy.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificEntropy.g.cs index 1a873b3a..ae38700b 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificEntropy.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificEntropy.g.cs @@ -118,5 +118,9 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two SpecificEntropy values, returning the absolute difference as a non-negative SpecificEntropy. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static SpecificEntropy operator -(SpecificEntropy left, SpecificEntropy right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// SpecificEntropy * Mass = Entropy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Entropy operator *(SpecificEntropy left, Mass right) => (SpecificHeat)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificGravity.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificGravity.g.cs index 103a5410..ade4c3eb 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificGravity.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificGravity.g.cs @@ -190,5 +190,29 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two SpecificGravity values, returning the absolute difference as a non-negative SpecificGravity. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static SpecificGravity operator -(SpecificGravity left, SpecificGravity right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// SpecificGravity * Ratio = Ratio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Ratio operator *(SpecificGravity left, Ratio right) => (Ratio)left * right; + + /// SpecificGravity * SignedRatio = SignedRatio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SignedRatio operator *(SpecificGravity left, SignedRatio right) => (Ratio)left * right; + + /// SpecificGravity / Duration = Frequency, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Frequency operator /(SpecificGravity left, Duration right) => (Ratio)left / right; + + /// SpecificGravity / Frequency = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(SpecificGravity left, Frequency right) => (Ratio)left / right; + + /// SpecificGravity / Temperature = ThermalExpansionCoefficient, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ThermalExpansionCoefficient operator /(SpecificGravity left, Temperature right) => (Ratio)left / right; + + /// SpecificGravity / ThermalExpansionCoefficient = Temperature, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Temperature operator /(SpecificGravity left, ThermalExpansionCoefficient right) => (Ratio)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificKineticEnergy.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificKineticEnergy.g.cs index 9ef05310..93231866 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificKineticEnergy.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificKineticEnergy.g.cs @@ -118,5 +118,9 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two SpecificKineticEnergy values, returning the absolute difference as a non-negative SpecificKineticEnergy. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static SpecificKineticEnergy operator -(SpecificKineticEnergy left, SpecificKineticEnergy right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// SpecificKineticEnergy * Length = GravitationalParameter, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static GravitationalParameter operator *(SpecificKineticEnergy left, Length right) => (SpecificEnergyMagnitude)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/StandardGravitationalParameter.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/StandardGravitationalParameter.g.cs index 74c69c8e..cd66f7bd 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/StandardGravitationalParameter.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/StandardGravitationalParameter.g.cs @@ -126,5 +126,13 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two StandardGravitationalParameter values, returning the absolute difference as a non-negative StandardGravitationalParameter. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static StandardGravitationalParameter operator -(StandardGravitationalParameter left, StandardGravitationalParameter right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// StandardGravitationalParameter / Area = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator /(StandardGravitationalParameter left, Area right) => (GravitationalParameter)left / right; + + /// StandardGravitationalParameter / Length = SpecificEnergyMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SpecificEnergyMagnitude operator /(StandardGravitationalParameter left, Length right) => (GravitationalParameter)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Stress.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Stress.g.cs index f73f0f70..8e33348d 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Stress.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Stress.g.cs @@ -158,5 +158,17 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Stress values, returning the absolute difference as a non-negative Stress. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Stress operator -(Stress left, Stress right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Stress * Area = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(Stress left, Area right) => (Pressure)left * right; + + /// Stress * Volume = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Stress left, Volume right) => (Pressure)left * right; + + /// Stress * Sensitivity = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator *(Stress left, Sensitivity right) => (Pressure)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SurfaceArea.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SurfaceArea.g.cs index 3e81fd41..b6fd3196 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SurfaceArea.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SurfaceArea.g.cs @@ -174,5 +174,41 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two SurfaceArea values, returning the absolute difference as a non-negative SurfaceArea. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static SurfaceArea operator -(SurfaceArea left, SurfaceArea right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// SurfaceArea / Length = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(SurfaceArea left, Length right) => (Area)left / right; + + /// SurfaceArea * Length = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator *(SurfaceArea left, Length right) => (Area)left * right; + + /// SurfaceArea * Pressure = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(SurfaceArea left, Pressure right) => (Area)left * right; + + /// SurfaceArea * ElectricFieldMagnitude = ElectricFlux, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ElectricFlux operator *(SurfaceArea left, ElectricFieldMagnitude right) => (Area)left * right; + + /// SurfaceArea * Illuminance = LuminousFlux, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static LuminousFlux operator *(SurfaceArea left, Illuminance right) => (Area)left * right; + + /// SurfaceArea * MagneticFluxDensityMagnitude = MagneticFlux, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MagneticFlux operator *(SurfaceArea left, MagneticFluxDensityMagnitude right) => (Area)left * right; + + /// SurfaceArea * Irradiance = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(SurfaceArea left, Irradiance right) => (Area)left * right; + + /// SurfaceArea * Luminance = LuminousIntensity, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static LuminousIntensity operator *(SurfaceArea left, Luminance right) => (Area)left * right; + + /// SurfaceArea * AccelerationMagnitude = GravitationalParameter, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static GravitationalParameter operator *(SurfaceArea left, AccelerationMagnitude right) => (Area)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Tension.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Tension.g.cs index e9eec34a..9870eb42 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Tension.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Tension.g.cs @@ -142,5 +142,37 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Tension values, returning the absolute difference as a non-negative Tension. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Tension operator -(Tension left, Tension right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Tension / AccelerationMagnitude = Mass, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Mass operator /(Tension left, AccelerationMagnitude right) => (ForceMagnitude)left / right; + + /// Tension / Mass = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator /(Tension left, Mass right) => (ForceMagnitude)left / right; + + /// Tension * Length = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Tension left, Length right) => (ForceMagnitude)left * right; + + /// Tension * Duration = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(Tension left, Duration right) => (ForceMagnitude)left * right; + + /// Tension * Speed = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(Tension left, Speed right) => (ForceMagnitude)left * right; + + /// Tension / Area = Pressure, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Pressure operator /(Tension left, Area right) => (ForceMagnitude)left / right; + + /// Tension / Length = SurfaceTension, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SurfaceTension operator /(Tension left, Length right) => (ForceMagnitude)left / right; + + /// Tension / SurfaceTension = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(Tension left, SurfaceTension right) => (ForceMagnitude)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ThermalDiffusivity.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ThermalDiffusivity.g.cs index c525e3a2..bcbfaa50 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ThermalDiffusivity.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ThermalDiffusivity.g.cs @@ -126,5 +126,9 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two ThermalDiffusivity values, returning the absolute difference as a non-negative ThermalDiffusivity. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static ThermalDiffusivity operator -(ThermalDiffusivity left, ThermalDiffusivity right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// ThermalDiffusivity * Density = DynamicViscosity, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static DynamicViscosity operator *(ThermalDiffusivity left, Density right) => (KinematicViscosity)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ThermalEnergy.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ThermalEnergy.g.cs index 5c511ff3..67c6392e 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ThermalEnergy.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ThermalEnergy.g.cs @@ -182,5 +182,45 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two ThermalEnergy values, returning the absolute difference as a non-negative ThermalEnergy. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static ThermalEnergy operator -(ThermalEnergy left, ThermalEnergy right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// ThermalEnergy / Length = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator /(ThermalEnergy left, Length right) => (Energy)left / right; + + /// ThermalEnergy / ForceMagnitude = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(ThermalEnergy left, ForceMagnitude right) => (Energy)left / right; + + /// ThermalEnergy / Volume = Pressure, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Pressure operator /(ThermalEnergy left, Volume right) => (Energy)left / right; + + /// ThermalEnergy / Pressure = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator /(ThermalEnergy left, Pressure right) => (Energy)left / right; + + /// ThermalEnergy / Duration = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator /(ThermalEnergy left, Duration right) => (Energy)left / right; + + /// ThermalEnergy / Power = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(ThermalEnergy left, Power right) => (Energy)left / right; + + /// ThermalEnergy / Temperature = Entropy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Entropy operator /(ThermalEnergy left, Temperature right) => (Energy)left / right; + + /// ThermalEnergy / Entropy = Temperature, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Temperature operator /(ThermalEnergy left, Entropy right) => (Energy)left / right; + + /// ThermalEnergy / AmountOfSubstance = MolarEnergy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MolarEnergy operator /(ThermalEnergy left, AmountOfSubstance right) => (Energy)left / right; + + /// ThermalEnergy / MolarEnergy = AmountOfSubstance, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AmountOfSubstance operator /(ThermalEnergy left, MolarEnergy right) => (Energy)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Thickness.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Thickness.g.cs index 6eae6e83..aec084df 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Thickness.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Thickness.g.cs @@ -206,5 +206,45 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Thickness values, returning the absolute difference as a non-negative Thickness. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Thickness operator -(Thickness left, Thickness right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Thickness * Length = Area, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Area operator *(Thickness left, Length right) => (Length)left * right; + + /// Thickness * Area = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator *(Thickness left, Area right) => (Length)left * right; + + /// Thickness / Duration = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator /(Thickness left, Duration right) => (Length)left / right; + + /// Thickness / Speed = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(Thickness left, Speed right) => (Length)left / right; + + /// Thickness * Frequency = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(Thickness left, Frequency right) => (Length)left * right; + + /// Thickness * ForceMagnitude = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Thickness left, ForceMagnitude right) => (Length)left * right; + + /// Thickness * ElectricFieldMagnitude = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator *(Thickness left, ElectricFieldMagnitude right) => (Length)left * right; + + /// Thickness * ElectricField1D = Voltage, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Voltage operator *(Thickness left, ElectricField1D right) => (Length)left * right; + + /// Thickness * SurfaceTension = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(Thickness left, SurfaceTension right) => (Length)left * right; + + /// Thickness * SpecificEnergyMagnitude = GravitationalParameter, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static GravitationalParameter operator *(Thickness left, SpecificEnergyMagnitude right) => (Length)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Thrust.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Thrust.g.cs index faaea691..3f7b1c2e 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Thrust.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Thrust.g.cs @@ -142,5 +142,37 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Thrust values, returning the absolute difference as a non-negative Thrust. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Thrust operator -(Thrust left, Thrust right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Thrust / AccelerationMagnitude = Mass, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Mass operator /(Thrust left, AccelerationMagnitude right) => (ForceMagnitude)left / right; + + /// Thrust / Mass = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator /(Thrust left, Mass right) => (ForceMagnitude)left / right; + + /// Thrust * Length = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Thrust left, Length right) => (ForceMagnitude)left * right; + + /// Thrust * Duration = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(Thrust left, Duration right) => (ForceMagnitude)left * right; + + /// Thrust * Speed = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(Thrust left, Speed right) => (ForceMagnitude)left * right; + + /// Thrust / Area = Pressure, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Pressure operator /(Thrust left, Area right) => (ForceMagnitude)left / right; + + /// Thrust / Length = SurfaceTension, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SurfaceTension operator /(Thrust left, Length right) => (ForceMagnitude)left / right; + + /// Thrust / SurfaceTension = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(Thrust left, SurfaceTension right) => (ForceMagnitude)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ThrustVector.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ThrustVector.g.cs index eb121302..f7efeec0 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ThrustVector.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ThrustVector.g.cs @@ -146,6 +146,9 @@ public ThrustVector Normalize() /// Negates a vector. public static ThrustVector operator -(ThrustVector vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; + /// ThrustVector * Duration = Momentum3D, through . + public static Momentum3D operator *(ThrustVector left, Duration right) => (Force3D)left * right; + /// Implicit conversion to Force3D. public static implicit operator Force3D(ThrustVector value) => new() { X = value.X, Y = value.Y, Z = value.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/TimeConstant.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/TimeConstant.g.cs index 25247401..ab34248e 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/TimeConstant.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/TimeConstant.g.cs @@ -182,5 +182,189 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two TimeConstant values, returning the absolute difference as a non-negative TimeConstant. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static TimeConstant operator -(TimeConstant left, TimeConstant right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// TimeConstant * CurrentMagnitude = ChargeMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ChargeMagnitude operator *(TimeConstant left, CurrentMagnitude right) => (Duration)left * right; + + /// TimeConstant * Current1D = Charge, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Charge operator *(TimeConstant left, Current1D right) => (Duration)left * right; + + /// TimeConstant * Speed = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator *(TimeConstant left, Speed right) => (Duration)left * right; + + /// TimeConstant * Velocity1D = Displacement1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement1D operator *(TimeConstant left, Velocity1D right) => (Duration)left * right; + + /// TimeConstant * Velocity2D = Displacement2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement2D operator *(TimeConstant left, Velocity2D right) => (Duration)left * right; + + /// TimeConstant * Velocity3D = Displacement3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement3D operator *(TimeConstant left, Velocity3D right) => (Duration)left * right; + + /// TimeConstant * Velocity4D = Displacement4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Displacement4D operator *(TimeConstant left, Velocity4D right) => (Duration)left * right; + + /// TimeConstant * AccelerationMagnitude = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(TimeConstant left, AccelerationMagnitude right) => (Duration)left * right; + + /// TimeConstant * Acceleration1D = Velocity1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity1D operator *(TimeConstant left, Acceleration1D right) => (Duration)left * right; + + /// TimeConstant * Acceleration2D = Velocity2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity2D operator *(TimeConstant left, Acceleration2D right) => (Duration)left * right; + + /// TimeConstant * Acceleration3D = Velocity3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity3D operator *(TimeConstant left, Acceleration3D right) => (Duration)left * right; + + /// TimeConstant * Acceleration4D = Velocity4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Velocity4D operator *(TimeConstant left, Acceleration4D right) => (Duration)left * right; + + /// TimeConstant * JerkMagnitude = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator *(TimeConstant left, JerkMagnitude right) => (Duration)left * right; + + /// TimeConstant * Jerk1D = Acceleration1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration1D operator *(TimeConstant left, Jerk1D right) => (Duration)left * right; + + /// TimeConstant * Jerk2D = Acceleration2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration2D operator *(TimeConstant left, Jerk2D right) => (Duration)left * right; + + /// TimeConstant * Jerk3D = Acceleration3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration3D operator *(TimeConstant left, Jerk3D right) => (Duration)left * right; + + /// TimeConstant * Jerk4D = Acceleration4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Acceleration4D operator *(TimeConstant left, Jerk4D right) => (Duration)left * right; + + /// TimeConstant * SnapMagnitude = JerkMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static JerkMagnitude operator *(TimeConstant left, SnapMagnitude right) => (Duration)left * right; + + /// TimeConstant * Snap1D = Jerk1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk1D operator *(TimeConstant left, Snap1D right) => (Duration)left * right; + + /// TimeConstant * Snap2D = Jerk2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk2D operator *(TimeConstant left, Snap2D right) => (Duration)left * right; + + /// TimeConstant * Snap3D = Jerk3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk3D operator *(TimeConstant left, Snap3D right) => (Duration)left * right; + + /// TimeConstant * Snap4D = Jerk4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Jerk4D operator *(TimeConstant left, Snap4D right) => (Duration)left * right; + + /// TimeConstant * Frequency = Ratio, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Ratio operator *(TimeConstant left, Frequency right) => (Duration)left * right; + + /// TimeConstant * AngularSpeed = Angle, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Angle operator *(TimeConstant left, AngularSpeed right) => (Duration)left * right; + + /// TimeConstant * AngularVelocity1D = SignedAngle, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SignedAngle operator *(TimeConstant left, AngularVelocity1D right) => (Duration)left * right; + + /// TimeConstant * AngularVelocity3D = AngularDisplacement3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularDisplacement3D operator *(TimeConstant left, AngularVelocity3D right) => (Duration)left * right; + + /// TimeConstant * AngularAccelerationMagnitude = AngularSpeed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularSpeed operator *(TimeConstant left, AngularAccelerationMagnitude right) => (Duration)left * right; + + /// TimeConstant * AngularAcceleration1D = AngularVelocity1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularVelocity1D operator *(TimeConstant left, AngularAcceleration1D right) => (Duration)left * right; + + /// TimeConstant * AngularAcceleration3D = AngularVelocity3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularVelocity3D operator *(TimeConstant left, AngularAcceleration3D right) => (Duration)left * right; + + /// TimeConstant * AngularJerkMagnitude = AngularAccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularAccelerationMagnitude operator *(TimeConstant left, AngularJerkMagnitude right) => (Duration)left * right; + + /// TimeConstant * AngularJerk1D = AngularAcceleration1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularAcceleration1D operator *(TimeConstant left, AngularJerk1D right) => (Duration)left * right; + + /// TimeConstant * AngularJerk3D = AngularAcceleration3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularAcceleration3D operator *(TimeConstant left, AngularJerk3D right) => (Duration)left * right; + + /// TimeConstant * TorqueMagnitude = AngularMomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularMomentumMagnitude operator *(TimeConstant left, TorqueMagnitude right) => (Duration)left * right; + + /// TimeConstant * Torque1D = AngularMomentum1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularMomentum1D operator *(TimeConstant left, Torque1D right) => (Duration)left * right; + + /// TimeConstant * Torque3D = AngularMomentum3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AngularMomentum3D operator *(TimeConstant left, Torque3D right) => (Duration)left * right; + + /// TimeConstant * ForceMagnitude = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(TimeConstant left, ForceMagnitude right) => (Duration)left * right; + + /// TimeConstant * Force1D = Momentum1D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum1D operator *(TimeConstant left, Force1D right) => (Duration)left * right; + + /// TimeConstant * Force2D = Momentum2D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum2D operator *(TimeConstant left, Force2D right) => (Duration)left * right; + + /// TimeConstant * Force3D = Momentum3D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum3D operator *(TimeConstant left, Force3D right) => (Duration)left * right; + + /// TimeConstant * Force4D = Momentum4D, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Momentum4D operator *(TimeConstant left, Force4D right) => (Duration)left * right; + + /// TimeConstant * Power = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(TimeConstant left, Power right) => (Duration)left * right; + + /// TimeConstant * VolumetricFlowRate = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator *(TimeConstant left, VolumetricFlowRate right) => (Duration)left * right; + + /// TimeConstant * MassFlowRate = Mass, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Mass operator *(TimeConstant left, MassFlowRate right) => (Duration)left * right; + + /// TimeConstant * CatalyticActivity = AmountOfSubstance, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AmountOfSubstance operator *(TimeConstant left, CatalyticActivity right) => (Duration)left * right; + + /// TimeConstant * ReactionRate = Concentration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Concentration operator *(TimeConstant left, ReactionRate right) => (Duration)left * right; + + /// TimeConstant * VoltageMagnitude = MagneticFlux, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MagneticFlux operator *(TimeConstant left, VoltageMagnitude right) => (Duration)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Translation3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Translation3D.g.cs index a6bd9f74..38fbf13b 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Translation3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Translation3D.g.cs @@ -202,6 +202,9 @@ public Translation3D Normalize() /// Negates a vector. public static Translation3D operator -(Translation3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; + /// Translation3D / Duration = Velocity3D, through . + public static Velocity3D operator /(Translation3D left, Duration right) => (Displacement3D)left / right; + /// Implicit conversion to Displacement3D. public static implicit operator Displacement3D(Translation3D value) => new() { X = value.X, Y = value.Y, Z = value.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/VoltageDrop.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/VoltageDrop.g.cs index 12a202db..8b824c18 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/VoltageDrop.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/VoltageDrop.g.cs @@ -126,5 +126,45 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two VoltageDrop values, returning the absolute difference as a non-negative VoltageDrop. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static VoltageDrop operator -(VoltageDrop left, VoltageDrop right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// VoltageDrop / Resistance = CurrentMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static CurrentMagnitude operator /(VoltageDrop left, Resistance right) => (VoltageMagnitude)left / right; + + /// VoltageDrop / CurrentMagnitude = Resistance, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Resistance operator /(VoltageDrop left, CurrentMagnitude right) => (VoltageMagnitude)left / right; + + /// VoltageDrop * CurrentMagnitude = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(VoltageDrop left, CurrentMagnitude right) => (VoltageMagnitude)left * right; + + /// VoltageDrop / Length = ElectricFieldMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ElectricFieldMagnitude operator /(VoltageDrop left, Length right) => (VoltageMagnitude)left / right; + + /// VoltageDrop / ElectricFieldMagnitude = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(VoltageDrop left, ElectricFieldMagnitude right) => (VoltageMagnitude)left / right; + + /// VoltageDrop * Capacitance = ChargeMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ChargeMagnitude operator *(VoltageDrop left, Capacitance right) => (VoltageMagnitude)left * right; + + /// VoltageDrop * Conductance = CurrentMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static CurrentMagnitude operator *(VoltageDrop left, Conductance right) => (VoltageMagnitude)left * right; + + /// VoltageDrop * Duration = MagneticFlux, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MagneticFlux operator *(VoltageDrop left, Duration right) => (VoltageMagnitude)left * right; + + /// VoltageDrop / Pressure = Sensitivity, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Sensitivity operator /(VoltageDrop left, Pressure right) => (VoltageMagnitude)left / right; + + /// VoltageDrop / Sensitivity = Pressure, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Pressure operator /(VoltageDrop left, Sensitivity right) => (VoltageMagnitude)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Wavelength.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Wavelength.g.cs index d2b90995..b4122a1d 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Wavelength.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Wavelength.g.cs @@ -206,5 +206,45 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Wavelength values, returning the absolute difference as a positive Wavelength. Throws when the two are equal, since a Wavelength cannot be zero; widen to first for a difference that may be. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Wavelength operator -(Wavelength left, Wavelength right) => Create(Vector0Guards.EnsurePositive(T.Abs(left.Quantity - right.Quantity), nameof(right))); + + /// Wavelength * Length = Area, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Area operator *(Wavelength left, Length right) => (Length)left * right; + + /// Wavelength * Area = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator *(Wavelength left, Area right) => (Length)left * right; + + /// Wavelength / Duration = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator /(Wavelength left, Duration right) => (Length)left / right; + + /// Wavelength / Speed = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(Wavelength left, Speed right) => (Length)left / right; + + /// Wavelength * Frequency = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(Wavelength left, Frequency right) => (Length)left * right; + + /// Wavelength * ForceMagnitude = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Wavelength left, ForceMagnitude right) => (Length)left * right; + + /// Wavelength * ElectricFieldMagnitude = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator *(Wavelength left, ElectricFieldMagnitude right) => (Length)left * right; + + /// Wavelength * ElectricField1D = Voltage, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Voltage operator *(Wavelength left, ElectricField1D right) => (Length)left * right; + + /// Wavelength * SurfaceTension = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(Wavelength left, SurfaceTension right) => (Length)left * right; + + /// Wavelength * SpecificEnergyMagnitude = GravitationalParameter, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static GravitationalParameter operator *(Wavelength left, SpecificEnergyMagnitude right) => (Length)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Weight.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Weight.g.cs index 315d9e58..d9dae496 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Weight.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Weight.g.cs @@ -142,5 +142,37 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Weight values, returning the absolute difference as a non-negative Weight. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Weight operator -(Weight left, Weight right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Weight / AccelerationMagnitude = Mass, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Mass operator /(Weight left, AccelerationMagnitude right) => (ForceMagnitude)left / right; + + /// Weight / Mass = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator /(Weight left, Mass right) => (ForceMagnitude)left / right; + + /// Weight * Length = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Weight left, Length right) => (ForceMagnitude)left * right; + + /// Weight * Duration = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(Weight left, Duration right) => (ForceMagnitude)left * right; + + /// Weight * Speed = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(Weight left, Speed right) => (ForceMagnitude)left * right; + + /// Weight / Area = Pressure, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Pressure operator /(Weight left, Area right) => (ForceMagnitude)left / right; + + /// Weight / Length = SurfaceTension, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static SurfaceTension operator /(Weight left, Length right) => (ForceMagnitude)left / right; + + /// Weight / SurfaceTension = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(Weight left, SurfaceTension right) => (ForceMagnitude)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WeightVector.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WeightVector.g.cs index 400971b7..e9c6dd94 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WeightVector.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WeightVector.g.cs @@ -146,6 +146,9 @@ public WeightVector Normalize() /// Negates a vector. public static WeightVector operator -(WeightVector vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; + /// WeightVector * Duration = Momentum3D, through . + public static Momentum3D operator *(WeightVector left, Duration right) => (Force3D)left * right; + /// Implicit conversion to Force3D. public static implicit operator Force3D(WeightVector value) => new() { X = value.X, Y = value.Y, Z = value.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Width.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Width.g.cs index a74b2bef..6891e40a 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Width.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Width.g.cs @@ -206,5 +206,45 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Width values, returning the absolute difference as a non-negative Width. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Width operator -(Width left, Width right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Width * Length = Area, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Area operator *(Width left, Length right) => (Length)left * right; + + /// Width * Area = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator *(Width left, Area right) => (Length)left * right; + + /// Width / Duration = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator /(Width left, Duration right) => (Length)left / right; + + /// Width / Speed = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(Width left, Speed right) => (Length)left / right; + + /// Width * Frequency = Speed, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Speed operator *(Width left, Frequency right) => (Length)left * right; + + /// Width * ForceMagnitude = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(Width left, ForceMagnitude right) => (Length)left * right; + + /// Width * ElectricFieldMagnitude = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator *(Width left, ElectricFieldMagnitude right) => (Length)left * right; + + /// Width * ElectricField1D = Voltage, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Voltage operator *(Width left, ElectricField1D right) => (Length)left * right; + + /// Width * SurfaceTension = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(Width left, SurfaceTension right) => (Length)left * right; + + /// Width * SpecificEnergyMagnitude = GravitationalParameter, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static GravitationalParameter operator *(Width left, SpecificEnergyMagnitude right) => (Length)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WindSpeed.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WindSpeed.g.cs index 2d8c9fe6..7cc1cc4b 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WindSpeed.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WindSpeed.g.cs @@ -158,5 +158,33 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two WindSpeed values, returning the absolute difference as a non-negative WindSpeed. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static WindSpeed operator -(WindSpeed left, WindSpeed right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// WindSpeed * Mass = MomentumMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MomentumMagnitude operator *(WindSpeed left, Mass right) => (Speed)left * right; + + /// WindSpeed * Duration = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator *(WindSpeed left, Duration right) => (Speed)left * right; + + /// WindSpeed / Duration = AccelerationMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AccelerationMagnitude operator /(WindSpeed left, Duration right) => (Speed)left / right; + + /// WindSpeed / AccelerationMagnitude = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(WindSpeed left, AccelerationMagnitude right) => (Speed)left / right; + + /// WindSpeed / Length = Frequency, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Frequency operator /(WindSpeed left, Length right) => (Speed)left / right; + + /// WindSpeed / Frequency = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(WindSpeed left, Frequency right) => (Speed)left / right; + + /// WindSpeed * ForceMagnitude = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator *(WindSpeed left, ForceMagnitude right) => (Speed)left * right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WindVelocity3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WindVelocity3D.g.cs index 47ad968b..cf9ab66d 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WindVelocity3D.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/WindVelocity3D.g.cs @@ -160,6 +160,12 @@ public WindVelocity3D Normalize() /// Negates a vector. public static WindVelocity3D operator -(WindVelocity3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z }; + /// WindVelocity3D * Duration = Displacement3D, through . + public static Displacement3D operator *(WindVelocity3D left, Duration right) => (Velocity3D)left * right; + + /// WindVelocity3D / Duration = Acceleration3D, through . + public static Acceleration3D operator /(WindVelocity3D left, Duration right) => (Velocity3D)left / right; + /// Implicit conversion to Velocity3D. public static implicit operator Velocity3D(WindVelocity3D value) => new() { X = value.X, Y = value.Y, Z = value.Z }; diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Work.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Work.g.cs index 7852c592..335704a3 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Work.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Work.g.cs @@ -182,5 +182,45 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two Work values, returning the absolute difference as a non-negative Work. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Work operator -(Work left, Work right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// Work / Length = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator /(Work left, Length right) => (Energy)left / right; + + /// Work / ForceMagnitude = Length, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Length operator /(Work left, ForceMagnitude right) => (Energy)left / right; + + /// Work / Volume = Pressure, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Pressure operator /(Work left, Volume right) => (Energy)left / right; + + /// Work / Pressure = Volume, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Volume operator /(Work left, Pressure right) => (Energy)left / right; + + /// Work / Duration = Power, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Power operator /(Work left, Duration right) => (Energy)left / right; + + /// Work / Power = Duration, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Duration operator /(Work left, Power right) => (Energy)left / right; + + /// Work / Temperature = Entropy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Entropy operator /(Work left, Temperature right) => (Energy)left / right; + + /// Work / Entropy = Temperature, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Temperature operator /(Work left, Entropy right) => (Energy)left / right; + + /// Work / AmountOfSubstance = MolarEnergy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static MolarEnergy operator /(Work left, AmountOfSubstance right) => (Energy)left / right; + + /// Work / MolarEnergy = AmountOfSubstance, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static AmountOfSubstance operator /(Work left, MolarEnergy right) => (Energy)left / right; } diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/YoungsModulus.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/YoungsModulus.g.cs index 98fcf3df..3bea4c8a 100644 --- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/YoungsModulus.g.cs +++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/YoungsModulus.g.cs @@ -158,5 +158,17 @@ namespace ktsu.Semantics.Quantities; /// Subtracts two YoungsModulus values, returning the absolute difference as a non-negative YoungsModulus. [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static YoungsModulus operator -(YoungsModulus left, YoungsModulus right) => Create(T.Abs(left.Quantity - right.Quantity)); + + /// YoungsModulus * Area = ForceMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static ForceMagnitude operator *(YoungsModulus left, Area right) => (Pressure)left * right; + + /// YoungsModulus * Volume = Energy, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static Energy operator *(YoungsModulus left, Volume right) => (Pressure)left * right; + + /// YoungsModulus * Sensitivity = VoltageMagnitude, through . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] + public static VoltageMagnitude operator *(YoungsModulus left, Sensitivity right) => (Pressure)left * right; } diff --git a/Semantics.SourceGenerators/Generators/QuantitiesGenerator.cs b/Semantics.SourceGenerators/Generators/QuantitiesGenerator.cs index 07792cd5..22478f71 100644 --- a/Semantics.SourceGenerators/Generators/QuantitiesGenerator.cs +++ b/Semantics.SourceGenerators/Generators/QuantitiesGenerator.cs @@ -1381,6 +1381,26 @@ private void EmitOverloadType( }); } + // Relationship operators reach an overload by forwarding to its base (#456). C# looks for an operator only + // on the two operand types and never widens the left operand to find one, so without these + // Distance / Duration did not compile while Duration * Distance did. + foreach (OperatorInfo op in ForwardedOperators(baseTypeName, emission)) + { + cls.Members.Add(new MethodTemplate() + { + Comments = {$"/// {typeName} {op.Op} {op.RightTypeName} = {op.ReturnTypeName}, through ."}, + Attributes = {Emit.PhysicsOperatorSuppression}, + Keywords = {Emit.Public, Emit.Static, $"{op.ReturnTypeName}"}, + Name = $"operator {op.Op}", + Parameters = + { + new ParameterTemplate { Type = fullType, Name = "left" }, + new ParameterTemplate { Type = $"{op.RightTypeName}", Name = Emit.RightParameter }, + }, + BodyFactory = (body) => body.Write($"=> ({baseFullType})left {op.Op} right;"), + }); + } + // Relationship methods (e.g., Diameter.ToRadius(), Diameter.FromRadius()). The one // thing an overload declares that the vocabulary does not carry: these are C# // expressions written in the metadata and pasted through, so there is nothing in @@ -1472,6 +1492,14 @@ private static void EmitVectorOverloadType( WriteVectorMethods(cb, fullType, components, dims); WriteVectorOperators(cb, fullType, components); + // Relationship operators, forwarded to the base as the scalar overloads do (#456). + foreach (OperatorInfo op in ForwardedOperators(baseTypeName, emission)) + { + cb.WriteLine($"/// {typeName} {op.Op} {op.RightTypeName} = {op.ReturnTypeName}, through ."); + cb.WriteLine($"public static {op.ReturnTypeName} operator {op.Op}({fullType} left, {op.RightTypeName} right) => ({baseFullType})left {op.Op} right;"); + cb.NewLine(); + } + // Implicit widening to base string baseInit = string.Join(", ", components.Select(c => $"{c} = value.{c}")); cb.WriteLine($"/// Implicit conversion to {baseTypeName}."); @@ -1491,6 +1519,41 @@ private static void EmitVectorOverloadType( #region Operator Emission Helpers + /// + /// The relationship operators a base type declares with itself on the left, which an overload of it forwards. + /// + /// + /// Every relationship operator is declared on its left operand's type, so one with the base on the right is + /// already reachable from an overload, which widens to it there. Forwarding only the left-hand ones is also + /// what keeps a product of two overloads unambiguous: for Width * Height only (Width, Length) + /// applies, since Width does not convert to Height. The filter matches what + /// and actually write. + /// + private static IEnumerable ForwardedOperators(string baseTypeName, Emission emission) + { + if (!emission.OperatorsByOwner.TryGetValue(baseTypeName, out List? ops)) + { + yield break; + } + + HashSet signatures = []; + foreach (OperatorInfo op in ops) + { + int leftForm = GetFormOrDefault(emission.TypeFormMap, op.LeftTypeName); + int rightForm = GetFormOrDefault(emission.TypeFormMap, op.RightTypeName); + int resultForm = GetFormOrDefault(emission.TypeFormMap, op.ReturnTypeName); + + bool emitted = (leftForm <= 1 && rightForm <= 1) + || (resultForm >= 2 && leftForm >= 2 && rightForm <= 1) + || (resultForm >= 2 && leftForm <= 1 && rightForm >= 2 && op.Op == "*"); + + if (op.LeftTypeName == baseTypeName && emitted && signatures.Add($"{op.Op}:{op.RightTypeName}")) + { + yield return op; + } + } + } + private static void EmitScalarOperators(ClassTemplate cls, string ownerTypeName, Emission emission) { if (!emission.OperatorsByOwner.TryGetValue(ownerTypeName, out List? ops)) diff --git a/Semantics.Test/Quantities/GeneratorOutputInvariantTests.cs b/Semantics.Test/Quantities/GeneratorOutputInvariantTests.cs index a3024d35..5ff977f2 100644 --- a/Semantics.Test/Quantities/GeneratorOutputInvariantTests.cs +++ b/Semantics.Test/Quantities/GeneratorOutputInvariantTests.cs @@ -96,6 +96,21 @@ public void EveryCrossDimensionalMultiplicationHasBothOperandOrders() } } + // A semantic overload forwards its base's products with itself on the left (#456). The swapped order + // needs no operator of its own: the base's operator is declared on the other operand's type, and the + // overload widens to the base there. + Dictionary baseOf = []; + foreach (Type type in types) + { + foreach (MethodInfo m in type.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly)) + { + if (m.Name == "op_Implicit" && m.GetParameters()[0].ParameterType.Name == type.Name && m.ReturnType.Namespace == type.Namespace) + { + baseOf[type.Name] = m.ReturnType.Name; + } + } + } + // For every cross-dimensional product (operands of distinct types), the swapped pair // should also be present with the same return. Same-type products (T * T) are exempt // because there is no swap — they're idempotent under reorder. @@ -107,7 +122,8 @@ public void EveryCrossDimensionalMultiplicationHasBothOperandOrders() continue; } - if (!observed.Contains((right, left, result))) + bool reachedThroughBase = baseOf.TryGetValue(left, out string? leftBase) && observed.Contains((right, leftBase, result)); + if (!observed.Contains((right, left, result)) && !reachedThroughBase) { missing.Add($"missing reverse pair: {right} * {left} -> {result} (forward {left} * {right} -> {result} exists)"); } diff --git a/Semantics.Test/Quantities/OverloadRelationshipOperatorTests.cs b/Semantics.Test/Quantities/OverloadRelationshipOperatorTests.cs new file mode 100644 index 00000000..f0a05ad0 --- /dev/null +++ b/Semantics.Test/Quantities/OverloadRelationshipOperatorTests.cs @@ -0,0 +1,68 @@ +// Copyright (c) 2023-2026 ktsu-dev contributors + +namespace ktsu.Semantics.Test.Quantities; + +using ktsu.Semantics.Quantities; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +/// +/// Issue #456: a semantic overload on the left of a relationship operator reaches its base's operator. +/// Each of these failed to compile with CS0019 before, so compiling is half of what is tested. +/// +[TestClass] +public sealed class OverloadRelationshipOperatorTests +{ + private const double Tolerance = 1e-12; + + [TestMethod] + public void DistanceOverDuration_IsASpeed() + { + Speed speed = Distance.FromMeter(100) / Duration.FromSecond(10); + Assert.AreEqual(10.0, speed.Value, Tolerance); + } + + [TestMethod] + public void WidthTimesWidth_IsAnArea() + { + Width width = Width.FromMeter(2); + Area area = width * width; + Assert.AreEqual(4.0, area.Value, Tolerance); + } + + [TestMethod] + public void WidthTimesHeight_IsAnArea() + { + Area area = Width.FromMeter(2) * Height.FromMeter(3); + Assert.AreEqual(6.0, area.Value, Tolerance); + } + + [TestMethod] + public void WeightTimesHeight_IsAnEnergy() + { + Energy energy = Weight.FromNewton(9.8) * Height.FromMeter(10); + Assert.AreEqual(98.0, energy.Value, 1e-9); + } + + [TestMethod] + public void OperandOrder_NoLongerDecidesWhetherItCompiles() + { + Width width = Width.FromMeter(2); + ForceMagnitude force = ForceMagnitude.FromNewton(3); + + Energy leftFirst = width * force; + Energy rightFirst = force * width; + + Assert.AreEqual(rightFirst.Value, leftFirst.Value, Tolerance); + Assert.AreEqual(6.0, leftFirst.Value, Tolerance); + } + + [TestMethod] + public void WindVelocityTimesDuration_IsADisplacement() + { + Displacement3D displacement = WindVelocity3D.FromMeterPerSecond(1, 2, 3) * Duration.FromSecond(2); + + Assert.AreEqual(2.0, displacement.X, Tolerance); + Assert.AreEqual(4.0, displacement.Y, Tolerance); + Assert.AreEqual(6.0, displacement.Z, Tolerance); + } +} diff --git a/docs/migration-guide-2.0.md b/docs/migration-guide-2.0.md index 7e2dfad2..0e67a7a1 100644 --- a/docs/migration-guide-2.0.md +++ b/docs/migration-guide-2.0.md @@ -96,8 +96,9 @@ Force1D net = thrustSigned - brakeSigned; A `Weight` is implicitly a `ForceMagnitude`; converting back requires `Weight.From(force)` or an explicit cast. Cross-dimensional operators are -defined on the base types and apply to overloads through widening — Ohm's law -works with an `Impedance` because it widens to `Resistance`. +defined on the base types, and each overload carries forwarding copies of the +ones with its base on the left, so Ohm's law works with an `Impedance` in either +operand position. (From 4.0 until #456 an overload on the left did not compile.) ### Storage-unit fixes (silent value changes!) diff --git a/docs/physics-generator.md b/docs/physics-generator.md index 3a7ff4bd..baf47c4b 100644 --- a/docs/physics-generator.md +++ b/docs/physics-generator.md @@ -83,11 +83,12 @@ The C# itself is described with the template object model from `ktsu.CodeBlocker An overload (e.g. `Width`, `Height`, `Depth` on `Length`) emits: -- A record extending the base type but with its own identity: `record Width : Length`. +- A `readonly record struct` of its own, `Width`, holding the same value its base would. Since 4.0 there is no inheritance between them. - Implicit operator widening to the base. - Explicit operator narrowing from the base. - A `From(base)` factory. - Per-relationship `To{Other}()` / `From{Other}()` methods if `relationships` is set. +- A forwarding copy of every relationship operator its base declares with the base on the left, such as `Speed operator /(Distance, Duration)`, written as a widening and a call to the base's operator (#456). C# looks for an operator only on the two operand types and never widens the left operand to find one, so without these `distance / duration` would not compile while `duration * distance` would. The base on the right needs no copy: that operator is declared on the other operand's type, and the overload widens to the base there. Results stay base types. Operator preservation (e.g. `Width + Width => Width` vs. `Width + Length => Length`) is generated, and follows the rule "narrowest-shared overload wins; otherwise widen to base". diff --git a/docs/strategy-unified-vector-quantities.md b/docs/strategy-unified-vector-quantities.md index ecada530..7f002897 100644 --- a/docs/strategy-unified-vector-quantities.md +++ b/docs/strategy-unified-vector-quantities.md @@ -355,7 +355,7 @@ dimension check can catch that, since a cross product and its negation have iden ### How Semantic Overloads Participate -Semantic overloads participate in cross-dimensional operations through implicit widening to their base type. The resolution chain: +Semantic overloads participate in cross-dimensional operations through forwarding operators and implicit widening to their base type. C# looks for an operator only on the two operand types, and never widens the left operand to find one, so each overload declares a copy of every relationship operator its base has with the base on the left (#456). The resolution chain: ```csharp // User writes: @@ -364,10 +364,10 @@ Height h = Height.FromMeter(10.0); // V0 overload of Length Energy e = w * h; // How does this work? // Resolution: -// 1. Weight implicitly converts to ForceMagnitude (base) +// 1. Weight declares operator *(Weight, Length), forwarded from ForceMagnitude * Length // 2. Height implicitly converts to Length (base) -// 3. ForceMagnitude * Length = Energy (generated operator) -// 4. Result: Energy +// 3. The forward widens Weight to ForceMagnitude and calls ForceMagnitude * Length = Energy +// 4. Result: Energy (always the base type, never an overload) ``` ```csharp From 920e4e5fdbd516fbdd8355b2aed93598640df14c Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 26 Oct 2026 10:56:30 +0000 Subject: [PATCH 5/8] [patch] C++ prelude: a representation widens implicitly and narrows only explicitly (#451) Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01RjhaUGAEJWfvbkaV4MjYkY --- .../GeneratedCppCompilesTests.cs | 59 +++++++++++++++++++ Semantics.Cpp/Prelude/quantity.hpp | 15 ++++- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/Semantics.Cpp.Test/GeneratedCppCompilesTests.cs b/Semantics.Cpp.Test/GeneratedCppCompilesTests.cs index ec43c8e0..9e557627 100644 --- a/Semantics.Cpp.Test/GeneratedCppCompilesTests.cs +++ b/Semantics.Cpp.Test/GeneratedCppCompilesTests.cs @@ -179,6 +179,65 @@ public void AComponentwiseProductWithTheWrongDimensionDoesNotCompile() Assert.AreNotEqual(0, exitCode, "a componentwise product whose exponents do not match the result type should be refused"); } + /// + /// A representation widens implicitly and narrows only when asked to. Issue #451. + /// + [TestMethod] + public void TheRepresentationWidensImplicitlyAndNarrowsExplicitly() + { + string directory = Emit(); + File.WriteAllText(Path.Join(directory, "widening.cpp"), """ + #include "quantities.hpp" + #include + + using L = holo::Dimension<1>; + using F = holo::Quantity; + using D = holo::Quantity; + + static_assert(std::is_convertible_v); + static_assert(!std::is_convertible_v); + static_assert(std::is_constructible_v); + static_assert(!std::is_convertible_v>); + + // float + double was ambiguous while each converted to the other. + static_assert(std::is_same_v); + static_assert((F{ 1.0f } + D{ 2.0 }).count() == 3.0); + static_assert(F{ D{ 0.5 } }.count() == 0.5f); + + int main() { return 0; } + """); + + (int exitCode, string output) = Compile(directory, "widening.cpp"); + + Assert.AreEqual(0, exitCode, $"widening should be implicit and mixed sums should resolve:\n{output}"); + } + + /// + /// Copy-initialising a narrower representation is refused rather than silently losing precision. + /// + [TestMethod] + public void AnImplicitNarrowingDoesNotCompile() + { + string directory = Emit(); + File.WriteAllText(Path.Join(directory, "narrowing.cpp"), """ + #include "quantities.hpp" + + using L = holo::Dimension<1>; + + holo::Quantity narrowed() + { + holo::Quantity f = holo::Quantity{ 1e40 }; + return f; + } + + int main() { return 0; } + """); + + (int exitCode, _) = Compile(directory, "narrowing.cpp"); + + Assert.AreNotEqual(0, exitCode, "double to float should need an explicit conversion"); + } + private static string Emit() { string directory = Path.Join(Path.GetTempPath(), $"semantics-cpp-{Guid.NewGuid():N}"); diff --git a/Semantics.Cpp/Prelude/quantity.hpp b/Semantics.Cpp/Prelude/quantity.hpp index 2fed4664..1ade622c 100644 --- a/Semantics.Cpp/Prelude/quantity.hpp +++ b/Semantics.Cpp/Prelude/quantity.hpp @@ -42,10 +42,21 @@ namespace @NAMESPACE@ { } - // Widening the representation of the same dimension is safe and implicit. + // Widening the representation of the same dimension is safe and implicit. Widening is what + // list-initialisation accepts, which refuses double to float and anything to an integer, so + // the conversion runs one way only and float + double resolves to double rather than being + // ambiguous. template - requires(!std::is_same_v && std::is_convertible_v) + requires(!std::is_same_v && requires(R2 r) { Rep{ r }; }) constexpr Quantity(Quantity other) noexcept + : value_(other.count()) + { + } + + // Narrowing is allowed, but only when it is written down. + template + requires(!std::is_same_v && std::is_convertible_v && !requires(R2 r) { Rep{ r }; }) + explicit constexpr Quantity(Quantity other) noexcept : value_(static_cast(other.count())) { } From 3c284f292179384f8b4bc3af5e736e716a775edb Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 26 Oct 2026 10:59:52 +0000 Subject: [PATCH 6/8] [patch] Strings: TryCreate rejects without exceptions; validation attributes and the WeakString setter cached per type (#443, #444) Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01RjhaUGAEJWfvbkaV4MjYkY --- Semantics.Strings/SemanticString.cs | 70 ++++++------------- .../SemanticStringValidationAttributes.cs | 3 +- .../Strategies/ValidateAllStrategy.cs | 18 ++++- .../Strategies/ValidateAnyStrategy.cs | 18 ++++- .../Strategies/ValidationStrategyFactory.cs | 4 +- .../Validation/ValidationAttributeCache.cs | 41 +++++++++++ .../SemanticStringCreationCostTests.cs | 69 ++++++++++++++++++ 7 files changed, 164 insertions(+), 59 deletions(-) create mode 100644 Semantics.Strings/Validation/ValidationAttributeCache.cs create mode 100644 Semantics.Test/SemanticStringCreationCostTests.cs diff --git a/Semantics.Strings/SemanticString.cs b/Semantics.Strings/SemanticString.cs index 685608e0..4f319c2f 100644 --- a/Semantics.Strings/SemanticString.cs +++ b/Semantics.Strings/SemanticString.cs @@ -7,7 +7,6 @@ namespace ktsu.Semantics.Strings; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; -using System.Reflection; using System.Text; /// @@ -533,7 +532,7 @@ public static TDest Create(string? value) where TDest : SemanticString { TDest newInstance = FromStringInternal(value: value); - return PerformValidation(value: newInstance); + return newInstance.IsValid() ? newInstance : throw new ArgumentException(message: ValidationFailureMessage(newInstance)); } /// @@ -629,28 +628,21 @@ private static TDest FromStringInternal(string? value) { Ensure.NotNull(value); - Type typeOfTDest = typeof(TDest); - TDest newInstance = (TDest)Ensure.NotNull(Activator.CreateInstance(type: typeOfTDest)); - PropertyInfo weakStringProperty = Ensure.NotNull(typeOfTDest.GetProperty(name: nameof(WeakString))); - weakStringProperty.SetValue(obj: newInstance, value: newInstance.MakeCanonical(value)); + TDest newInstance = Ensure.NotNull(Activator.CreateInstance()); + WeakStringSetter.Set(newInstance, newInstance.MakeCanonical(value)); return newInstance; } /// - /// Validates a semantic string instance and throws an exception if validation fails. + /// The init accessor as a delegate, looked up once per type rather than per value (#444). /// - /// The semantic string type being validated. - /// The semantic string instance to validate. - /// The validated semantic string instance. - /// The semantic string instance is null or fails validation. - private static TDest PerformValidation(TDest? value) + /// The semantic string type to set the value of. + private static class WeakStringSetter where TDest : SemanticString { - if (value == null || !value.IsValid()) - { - throw new ArgumentException(message: ValidationFailureMessage(value)); - } - return value; + internal static readonly Action Set = (Action)Delegate.CreateDelegate( + typeof(Action), + Ensure.NotNull(typeof(TDest).GetProperty(name: nameof(WeakString))?.GetSetMethod())); } /// @@ -796,14 +788,23 @@ private static bool TryFromString(string? value, out TDest? result) where TDest : SemanticString { result = null; + if (value is null) + { + return false; + } + + // A rejected value is the expected case here, so it is reported by the return value rather than by an + // exception, and its reasons are never put into words (#443). The catch is only for a MakeCanonical or a + // validator that rejects its input by throwing, as Create would report it. try { - if (value is null) + TDest instance = FromStringInternal(value); + if (!instance.IsValid()) { return false; } - result = Create(value); + result = instance; return true; } catch (ArgumentException) @@ -825,23 +826,7 @@ private static bool TryFromString(string? value, out TDest? result) /// private static bool TryFromCharArray(char[]? value, out TDest? result) where TDest : SemanticString - { - result = null; - try - { - if (value is null) - { - return false; - } - - result = Create(value); - return true; - } - catch (ArgumentException) - { - return false; - } - } + => TryFromString(value is null ? null : new string(value: value), out result); /// /// Attempts to create a new instance of the specified semantic string type from a read-only character span without throwing exceptions. @@ -857,18 +842,7 @@ private static bool TryFromCharArray(char[]? value, out TDest? result) /// private static bool TryFromReadOnlySpan(ReadOnlySpan value, out TDest? result) where TDest : SemanticString - { - result = null; - try - { - result = Create(value); - return true; - } - catch (ArgumentException) - { - return false; - } - } + => TryFromString(value.ToString(), out result); /// /// Gets this semantic string as a read-only span without allocation. diff --git a/Semantics.Strings/Validation/SemanticStringValidationAttributes.cs b/Semantics.Strings/Validation/SemanticStringValidationAttributes.cs index 360c80bd..c4e38ec0 100644 --- a/Semantics.Strings/Validation/SemanticStringValidationAttributes.cs +++ b/Semantics.Strings/Validation/SemanticStringValidationAttributes.cs @@ -42,8 +42,7 @@ public static IEnumerable GetValidationErrors(ISemanticString semanticSt { Ensure.NotNull(type); - foreach (SemanticStringValidationAttribute attribute in type.GetCustomAttributes(typeof(SemanticStringValidationAttribute), true) - .Cast() + foreach (SemanticStringValidationAttribute attribute in ValidationAttributeCache.Attributes(type) .Where(attribute => !attribute.Validate(semanticString))) { string[] errors = attribute is NativeSemanticStringValidationAttribute native diff --git a/Semantics.Strings/Validation/Strategies/ValidateAllStrategy.cs b/Semantics.Strings/Validation/Strategies/ValidateAllStrategy.cs index b066bdb8..d60e936a 100644 --- a/Semantics.Strings/Validation/Strategies/ValidateAllStrategy.cs +++ b/Semantics.Strings/Validation/Strategies/ValidateAllStrategy.cs @@ -12,8 +12,20 @@ public bool Validate(ISemanticString semanticString, Type type) { Ensure.NotNull(type); - SemanticStringValidationAttribute[] validationAttributes = [.. type.GetCustomAttributes(typeof(SemanticStringValidationAttribute), true) - .Cast()]; - return validationAttributes.Length == 0 || validationAttributes.All(attr => attr.Validate(semanticString)); + SemanticStringValidationAttribute[] validationAttributes = ValidationAttributeCache.Attributes(type); + if (validationAttributes.Length == 0) + { + return true; + } + + foreach (SemanticStringValidationAttribute attribute in validationAttributes) + { + if (!attribute.Validate(semanticString)) + { + return false; + } + } + + return true; } } diff --git a/Semantics.Strings/Validation/Strategies/ValidateAnyStrategy.cs b/Semantics.Strings/Validation/Strategies/ValidateAnyStrategy.cs index b9ec47f3..6ae4af4b 100644 --- a/Semantics.Strings/Validation/Strategies/ValidateAnyStrategy.cs +++ b/Semantics.Strings/Validation/Strategies/ValidateAnyStrategy.cs @@ -12,8 +12,20 @@ public bool Validate(ISemanticString semanticString, Type type) { Ensure.NotNull(type); - SemanticStringValidationAttribute[] validationAttributes = [.. type.GetCustomAttributes(typeof(SemanticStringValidationAttribute), true) - .Cast()]; - return validationAttributes.Length == 0 || validationAttributes.Any(attr => attr.Validate(semanticString)); + SemanticStringValidationAttribute[] validationAttributes = ValidationAttributeCache.Attributes(type); + if (validationAttributes.Length == 0) + { + return true; + } + + foreach (SemanticStringValidationAttribute attribute in validationAttributes) + { + if (attribute.Validate(semanticString)) + { + return true; + } + } + + return false; } } diff --git a/Semantics.Strings/Validation/Strategies/ValidationStrategyFactory.cs b/Semantics.Strings/Validation/Strategies/ValidationStrategyFactory.cs index 3d486644..ebdb2008 100644 --- a/Semantics.Strings/Validation/Strategies/ValidationStrategyFactory.cs +++ b/Semantics.Strings/Validation/Strategies/ValidationStrategyFactory.cs @@ -19,8 +19,6 @@ public static IValidationStrategy CreateStrategy(Type type) { Ensure.NotNull(type); - // Check for ValidateAny attribute - object[] validateAnyAttributes = type.GetCustomAttributes(typeof(ValidateAnyAttribute), true); - return validateAnyAttributes.Length > 0 ? AnyStrategy : AllStrategy; + return ValidationAttributeCache.ValidatesAny(type) ? AnyStrategy : AllStrategy; } } diff --git a/Semantics.Strings/Validation/ValidationAttributeCache.cs b/Semantics.Strings/Validation/ValidationAttributeCache.cs new file mode 100644 index 00000000..49548ecc --- /dev/null +++ b/Semantics.Strings/Validation/ValidationAttributeCache.cs @@ -0,0 +1,41 @@ +// Copyright (c) 2023-2026 ktsu-dev contributors + +namespace ktsu.Semantics.Strings; + +using System; +using System.Collections.Concurrent; +using System.Linq; + +/// +/// The validation attributes a semantic string type declares, read once per type. +/// +/// +/// builds new attribute +/// instances on every call, and each builds its validator +/// lazily, so reading them per value allocated a validator per value validated (#444). Attributes are +/// immutable once constructed and their validators are stateless, so one set per type serves every thread. +/// +internal static class ValidationAttributeCache +{ + private static readonly ConcurrentDictionary Entries = new(); + + /// Gets the validation attributes declared on a type and its bases, in declaration order. + /// The semantic string type. + /// The attributes, shared between callers; do not modify the array. + public static SemanticStringValidationAttribute[] Attributes(Type type) => Get(type).Attributes; + + /// Gets whether a type is marked . + /// The semantic string type. + /// when any one attribute passing is enough. + public static bool ValidatesAny(Type type) => Get(type).ValidatesAny; + + private static Entry Get(Type type) + { + Ensure.NotNull(type); + return Entries.GetOrAdd(type, static t => new Entry( + [.. t.GetCustomAttributes(typeof(SemanticStringValidationAttribute), true).Cast()], + t.GetCustomAttributes(typeof(ValidateAnyAttribute), true).Length > 0)); + } + + private sealed record Entry(SemanticStringValidationAttribute[] Attributes, bool ValidatesAny); +} diff --git a/Semantics.Test/SemanticStringCreationCostTests.cs b/Semantics.Test/SemanticStringCreationCostTests.cs new file mode 100644 index 00000000..30dc2765 --- /dev/null +++ b/Semantics.Test/SemanticStringCreationCostTests.cs @@ -0,0 +1,69 @@ +// Copyright (c) 2023-2026 ktsu-dev contributors + +namespace ktsu.Semantics.Test; + +using System; +using System.Runtime.ExceptionServices; +using ktsu.Semantics.Strings; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +/// +/// Issue #443: rejecting a value through TryCreate throws nothing. Issue #444: a type's validation +/// attributes are read once rather than per value. +/// +[TestClass] +public sealed class SemanticStringCreationCostTests +{ + [ThreadStatic] + private static int exceptionsOnThisThread; + + private static void Count(object? sender, FirstChanceExceptionEventArgs e) => exceptionsOnThisThread++; + + [TestMethod] + public void TryCreate_RejectsWithoutThrowing() + { + AppDomain.CurrentDomain.FirstChanceException += Count; + try + { + exceptionsOnThisThread = 0; + + bool fromString = StartsWithValidSemanticString.TryCreate("Nope", out StartsWithValidSemanticString? a); + bool fromChars = StartsWithValidSemanticString.TryCreate("Nope".ToCharArray(), out StartsWithValidSemanticString? b); + bool fromSpan = StartsWithValidSemanticString.TryCreate("Nope".AsSpan(), out StartsWithValidSemanticString? c); + bool fromNull = StartsWithValidSemanticString.TryCreate((string?)null, out StartsWithValidSemanticString? d); + + Assert.IsFalse(fromString || fromChars || fromSpan || fromNull); + Assert.IsNull(a ?? b ?? c ?? d); + Assert.AreEqual(0, exceptionsOnThisThread); + } + finally + { + AppDomain.CurrentDomain.FirstChanceException -= Count; + } + } + + [TestMethod] + public void TryCreate_AcceptsAValidValue() + { + Assert.IsTrue(StartsWithValidSemanticString.TryCreate("Valid value", out StartsWithValidSemanticString? result)); + Assert.AreEqual("Valid value", result?.WeakString); + } + + [TestMethod] + public void Create_StillThrowsWithTheReasons() + { + ArgumentException error = Assert.ThrowsExactly(() => StartsWithValidSemanticString.Create("Nope")); + StringAssert.Contains(error.Message, "\"Nope\""); + StringAssert.Contains(error.Message, nameof(StartsWithValidSemanticString)); + } + + [TestMethod] + public void ValidationAttributes_AreReadOncePerType() + { + Type type = typeof(StartsWithValidSemanticString); + SemanticStringValidationAttribute[] first = ValidationAttributeCache.Attributes(type); + + Assert.HasCount(1, first); + Assert.AreSame(first, ValidationAttributeCache.Attributes(type)); + } +} From 117b10406803f3616e6c94359a17e9d9f50f9635 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 26 Oct 2026 11:01:02 +0000 Subject: [PATCH 7/8] Use Path.Join for test fixture paths Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01RjhaUGAEJWfvbkaV4MjYkY --- Semantics.Test/Paths/DotSegmentPathTests.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Semantics.Test/Paths/DotSegmentPathTests.cs b/Semantics.Test/Paths/DotSegmentPathTests.cs index 9bcf78fb..df45d463 100644 --- a/Semantics.Test/Paths/DotSegmentPathTests.cs +++ b/Semantics.Test/Paths/DotSegmentPathTests.cs @@ -147,13 +147,13 @@ protected override IFilePath CreateFilePath(string filePath) => [TestMethod] public void GetContents_SkipsAnEntryThatFailsValidation() { - string root = Path.Combine(Path.GetTempPath(), "semantics-contents-" + Guid.NewGuid().ToString("N")); + string root = Path.Join(Path.GetTempPath(), "semantics-contents-" + Guid.NewGuid().ToString("N")); Directory.CreateDirectory(root); try { - File.WriteAllText(Path.Combine(root, "ok.txt"), "ok"); - Directory.CreateDirectory(Path.Combine(root, "sub")); - File.WriteAllText(Path.Combine(root, "bad.txt"), "rejected"); + File.WriteAllText(Path.Join(root, "ok.txt"), "ok"); + Directory.CreateDirectory(Path.Join(root, "sub")); + File.WriteAllText(Path.Join(root, "bad.txt"), "rejected"); PickyDirectoryPath dir = PickyDirectoryPath.Create(root); List names = [.. dir.GetContents().Select(p => Path.GetFileName(p.ToString()) ?? "")]; @@ -172,13 +172,13 @@ public void GetContents_SkipsAnEntryThatFailsValidation() [TestCategory("OS-Specific")] public void GetContents_SkipsAnEntryPastTheWindowsLengthLimit() { - string root = Path.Combine(Path.GetTempPath(), "semantics-contents-" + Guid.NewGuid().ToString("N")); + string root = Path.Join(Path.GetTempPath(), "semantics-contents-" + Guid.NewGuid().ToString("N")); Directory.CreateDirectory(root); try { - File.WriteAllText(Path.Combine(root, "ok.txt"), "ok"); - Directory.CreateDirectory(Path.Combine(root, "sub")); - File.WriteAllText(Path.Combine(root, new string('x', 250) + ".txt"), "too long"); + File.WriteAllText(Path.Join(root, "ok.txt"), "ok"); + Directory.CreateDirectory(Path.Join(root, "sub")); + File.WriteAllText(Path.Join(root, new string('x', 250) + ".txt"), "too long"); List names = [.. Absolute(root).GetContents().Select(p => Path.GetFileName(p.ToString()) ?? "")]; From 8134f226b03c201e563079be091356e2e3283a27 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 26 Oct 2026 11:05:35 +0000 Subject: [PATCH 8/8] Address code-quality findings: zero pattern, local exception counter, explicit Where Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01RjhaUGAEJWfvbkaV4MjYkY --- Semantics.Quantities/StorageLiteral.cs | 2 +- .../Quantities/GeneratorOutputInvariantTests.cs | 8 +++----- .../SemanticStringCreationCostTests.cs | 17 +++++++++++------ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Semantics.Quantities/StorageLiteral.cs b/Semantics.Quantities/StorageLiteral.cs index 4026a84e..231cfedd 100644 --- a/Semantics.Quantities/StorageLiteral.cs +++ b/Semantics.Quantities/StorageLiteral.cs @@ -105,7 +105,7 @@ internal static T Constant(string literal, string name) double expected = double.Parse(literal, NumberStyles.Float, CultureInfo.InvariantCulture); T value = TryParseLiteral(literal, out T parsed) ? parsed : T.CreateChecked(expected); - if (expected != 0.0 && !KeepsPrecision(value, expected)) + if (expected is not 0.0 && !KeepsPrecision(value, expected)) { throw new ArithmeticException(string.Format( CultureInfo.InvariantCulture, diff --git a/Semantics.Test/Quantities/GeneratorOutputInvariantTests.cs b/Semantics.Test/Quantities/GeneratorOutputInvariantTests.cs index 5ff977f2..868bf050 100644 --- a/Semantics.Test/Quantities/GeneratorOutputInvariantTests.cs +++ b/Semantics.Test/Quantities/GeneratorOutputInvariantTests.cs @@ -102,12 +102,10 @@ public void EveryCrossDimensionalMultiplicationHasBothOperandOrders() Dictionary baseOf = []; foreach (Type type in types) { - foreach (MethodInfo m in type.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly)) + foreach (MethodInfo m in type.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly) + .Where(m => m.Name == "op_Implicit" && m.GetParameters()[0].ParameterType.Name == type.Name && m.ReturnType.Namespace == type.Namespace)) { - if (m.Name == "op_Implicit" && m.GetParameters()[0].ParameterType.Name == type.Name && m.ReturnType.Namespace == type.Namespace) - { - baseOf[type.Name] = m.ReturnType.Name; - } + baseOf[type.Name] = m.ReturnType.Name; } } diff --git a/Semantics.Test/SemanticStringCreationCostTests.cs b/Semantics.Test/SemanticStringCreationCostTests.cs index 30dc2765..68a261eb 100644 --- a/Semantics.Test/SemanticStringCreationCostTests.cs +++ b/Semantics.Test/SemanticStringCreationCostTests.cs @@ -14,18 +14,23 @@ namespace ktsu.Semantics.Test; [TestClass] public sealed class SemanticStringCreationCostTests { - [ThreadStatic] - private static int exceptionsOnThisThread; - - private static void Count(object? sender, FirstChanceExceptionEventArgs e) => exceptionsOnThisThread++; - [TestMethod] public void TryCreate_RejectsWithoutThrowing() { + // Tests run in parallel, so only exceptions thrown on this test's own thread count. + int thisThread = Environment.CurrentManagedThreadId; + int exceptionsOnThisThread = 0; + void Count(object? sender, FirstChanceExceptionEventArgs e) + { + if (Environment.CurrentManagedThreadId == thisThread) + { + exceptionsOnThisThread++; + } + } + AppDomain.CurrentDomain.FirstChanceException += Count; try { - exceptionsOnThisThread = 0; bool fromString = StartsWithValidSemanticString.TryCreate("Nope", out StartsWithValidSemanticString? a); bool fromChars = StartsWithValidSemanticString.TryCreate("Nope".ToCharArray(), out StartsWithValidSemanticString? b);