From 4a123a93d2977bcf79c5a3c166c795d7d9d88188 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 13 Jul 2026 01:25:07 +0000
Subject: [PATCH] test: add coverage-gap tests for Frac, Pow, Divide, and Clamp
- Frac: 5 tests (fractional parts for positive, negative, integer, zero;
and parity check against FractionalPart)
- Pow: negative-exponent guard (ArgumentOutOfRangeException) and
zero-exponent returns One
- Divide(long): zero-divisor guard (DivideByZeroException)
- Clamp: min-exceeds-max guard (ArgumentException)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../FixedPointNanoCoverageGapTests.cs | 84 +++++++++++++++++++
1 file changed, 84 insertions(+)
create mode 100644 tests/FixedPointNano.Tests/FixedPointNanoCoverageGapTests.cs
diff --git a/tests/FixedPointNano.Tests/FixedPointNanoCoverageGapTests.cs b/tests/FixedPointNano.Tests/FixedPointNanoCoverageGapTests.cs
new file mode 100644
index 0000000..0c9ede2
--- /dev/null
+++ b/tests/FixedPointNano.Tests/FixedPointNanoCoverageGapTests.cs
@@ -0,0 +1,84 @@
+using System;
+using Seerstone;
+
+namespace Seerstone.Tests;
+
+///
+/// Covers behaviours not exercised by the other test fixtures:
+/// Frac, Pow negative-exponent guard, Divide(long) zero guard,
+/// and Clamp invalid-range guard.
+///
+[TestFixture]
+public sealed class FixedPointNanoCoverageGapTests
+{
+ // -----------------------------------------------------------------------------------------
+ // Frac
+ // -----------------------------------------------------------------------------------------
+
+ [TestCase(1.75, 0.75, Description = "Positive fractional part")]
+ [TestCase(1.0, 0.0, Description = "Exact integer has zero Frac")]
+ [TestCase(-1.25, -0.25, Description = "Negative fractional part keeps sign")]
+ [TestCase(0.0, 0.0, Description = "Zero has zero Frac")]
+ public void FracShouldReturnFractionalPart(double input, double expected)
+ {
+ var value = FixedPointNano.FromDouble(input);
+ Assert.That(FixedPointNano.Frac(value).ToDouble(), Is.EqualTo(expected).Within(1e-9));
+ }
+
+ [Test]
+ public void FracShouldMatchFractionalPart()
+ {
+ var values = new[] { 1.5, -3.25, 0.0, 42.0, -0.999999999 };
+ foreach (var d in values)
+ {
+ var v = FixedPointNano.FromDouble(d);
+ Assert.That(FixedPointNano.Frac(v), Is.EqualTo(FixedPointNano.FractionalPart(v)),
+ $"Frac and FractionalPart differ for {d}");
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------
+ // Pow – negative exponent guard
+ // -----------------------------------------------------------------------------------------
+
+ [Test]
+ public void PowShouldThrowForNegativeExponent()
+ {
+ Assert.That(
+ () => FixedPointNano.Pow(FixedPointNano.One, -1),
+ Throws.TypeOf());
+ }
+
+ [Test]
+ public void PowZeroExponentShouldReturnOne()
+ {
+ var value = FixedPointNano.FromDecimal(7.5m);
+ Assert.That(FixedPointNano.Pow(value, 0), Is.EqualTo(FixedPointNano.One));
+ }
+
+ // -----------------------------------------------------------------------------------------
+ // Divide(FixedPointNano, long) – zero-divisor guard
+ // -----------------------------------------------------------------------------------------
+
+ [Test]
+ public void DivideByLongZeroShouldThrowDivideByZeroException()
+ {
+ Assert.That(
+ () => FixedPointNano.Divide(FixedPointNano.One, 0L),
+ Throws.TypeOf());
+ }
+
+ // -----------------------------------------------------------------------------------------
+ // Clamp – invalid range guard
+ // -----------------------------------------------------------------------------------------
+
+ [Test]
+ public void ClampShouldThrowWhenMinExceedsMax()
+ {
+ var min = FixedPointNano.FromDecimal(5m);
+ var max = FixedPointNano.FromDecimal(1m);
+ Assert.That(
+ () => FixedPointNano.Clamp(FixedPointNano.Zero, min, max),
+ Throws.TypeOf());
+ }
+}