From 122932185c8511d09e17a64850d39a86845ccdfa Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Sun, 20 Oct 2024 19:42:45 +0530 Subject: [PATCH 1/4] refactor: Enhance docs, add more tests in `AffineConverter` --- .../conversions/AffineConverter.java | 45 +++++++++++++- .../conversions/AffineConverterTest.java | 59 +++++++++++++++---- 2 files changed, 91 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/thealgorithms/conversions/AffineConverter.java b/src/main/java/com/thealgorithms/conversions/AffineConverter.java index a580b23f90f9..199a6dd517d5 100644 --- a/src/main/java/com/thealgorithms/conversions/AffineConverter.java +++ b/src/main/java/com/thealgorithms/conversions/AffineConverter.java @@ -1,23 +1,64 @@ package com.thealgorithms.conversions; +/** + * A utility class to perform affine transformations of the form: + * y = slope * x + intercept. + * + * This class supports inversion and composition of affine transformations. + * It is immutable, meaning each instance represents a fixed transformation. + */ public final class AffineConverter { private final double slope; private final double intercept; + + /** + * Constructs an AffineConverter with the given slope and intercept. + * + * @param inSlope The slope of the affine transformation. + * @param inIntercept The intercept (constant term) of the affine transformation. + * @throws IllegalArgumentException if either parameter is NaN. + */ public AffineConverter(final double inSlope, final double inIntercept) { + if (Double.isNaN(inSlope) || Double.isNaN(inIntercept)) { + throw new IllegalArgumentException("Slope and intercept must be valid numbers."); + } slope = inSlope; intercept = inIntercept; } + /** + * Converts the given input value using the affine transformation: + * result = slope * inValue + intercept. + * + * @param inValue The input value to convert. + * @return The transformed value. + */ public double convert(final double inValue) { return slope * inValue + intercept; } + /** + * Returns a new AffineConverter representing the inverse of the current transformation. + * The inverse of y = slope * x + intercept is x = (y - intercept) / slope. + * + * @return A new AffineConverter representing the inverse transformation. + * @throws AssertionError if the slope is zero, as the inverse would be undefined. + */ public AffineConverter invert() { - assert slope != 0.0; + assert slope != 0.0 : "Slope cannot be zero for inversion."; return new AffineConverter(1.0 / slope, -intercept / slope); } + /** + * Composes this affine transformation with another, returning a new AffineConverter. + * If this transformation is f(x) and the other is g(x), the result is f(g(x)). + * + * @param other Another AffineConverter to compose with. + * @return A new AffineConverter representing the composition of the two transformations. + */ public AffineConverter compose(final AffineConverter other) { - return new AffineConverter(slope * other.slope, slope * other.intercept + intercept); + double newSlope = slope * other.slope; + double newIntercept = slope * other.intercept + intercept; + return new AffineConverter(newSlope, newIntercept); } } diff --git a/src/test/java/com/thealgorithms/conversions/AffineConverterTest.java b/src/test/java/com/thealgorithms/conversions/AffineConverterTest.java index 2705955f68f6..5a65609d63cb 100644 --- a/src/test/java/com/thealgorithms/conversions/AffineConverterTest.java +++ b/src/test/java/com/thealgorithms/conversions/AffineConverterTest.java @@ -16,31 +16,43 @@ void setUp() { } @Test - void testConstructor() { + void testConstructorWithValidValues() { assertEquals(3.0, converter.convert(0.0), "Expected value when input is 0.0"); assertEquals(5.0, converter.convert(1.0), "Expected value when input is 1.0"); - assertEquals(7.0, converter.convert(2.0), "Expected value when input is 2.0"); } @Test - void testConvert() { - assertEquals(3.0, converter.convert(0.0), "Conversion at 0.0 should equal the intercept"); - assertEquals(7.0, converter.convert(2.0), "2.0 should convert to 7.0"); - assertEquals(11.0, converter.convert(4.0), "4.0 should convert to 11.0"); + void testConstructorWithInvalidValues() { + assertThrows(IllegalArgumentException.class, + () -> new AffineConverter(Double.NaN, 3.0), + "Constructor should throw IllegalArgumentException for NaN slope"); + } + + @Test + void testConvertWithNegativeValues() { + assertEquals(-1.0, converter.convert(-2.0), "Negative input should convert correctly"); + assertEquals(-3.0, new AffineConverter(-1.0, -1.0).convert(2.0), + "Slope and intercept can be negative"); + } + + @Test + void testConvertWithFloatingPointPrecision() { + double result = new AffineConverter(1.3333, 0.6667).convert(3.0); + assertEquals(4.6666, result, 1e-4, "Conversion should maintain floating-point precision"); } @Test void testInvert() { AffineConverter inverted = converter.invert(); - assertEquals(0.0, inverted.convert(3.0), "Inverted converter should return 0.0 for input 3.0"); - assertEquals(1.0, inverted.convert(5.0), "Inverted converter should return 1.0 for input 5.0"); - assertEquals(2.0, inverted.convert(7.0), "Inverted converter should return 2.0 for input 7.0"); + assertEquals(0.0, inverted.convert(3.0), "Inverted should return 0.0 for input 3.0"); + assertEquals(1.0, inverted.convert(5.0), "Inverted should return 1.0 for input 5.0"); } @Test void testInvertWithZeroSlope() { AffineConverter zeroSlopeConverter = new AffineConverter(0.0, 3.0); - assertThrows(AssertionError.class, zeroSlopeConverter::invert, "Invert should throw assertion error when slope is zero"); + assertThrows(AssertionError.class, zeroSlopeConverter::invert, + "Invert should throw AssertionError when slope is zero"); } @Test @@ -50,6 +62,31 @@ void testCompose() { assertEquals(7.0, composed.convert(0.0), "Expected composed conversion at 0.0"); assertEquals(9.0, composed.convert(1.0), "Expected composed conversion at 1.0"); - assertEquals(11.0, composed.convert(2.0), "Expected composed conversion at 2.0"); + } + + @Test + void testMultipleCompositions() { + AffineConverter c1 = new AffineConverter(2.0, 1.0); + AffineConverter c2 = new AffineConverter(3.0, -2.0); + AffineConverter c3 = c1.compose(c2); // (2x + 1) ∘ (3x - 2) => 6x - 1 + + assertEquals(-3.0, c3.convert(0.0), "Composed transformation should return -3.0 at 0.0"); + assertEquals(3.0, c3.convert(1.0), "Composed transformation should return 3.0 at 1.0"); + } + + @Test + void testIdentityComposition() { + AffineConverter identity = new AffineConverter(1.0, 0.0); + AffineConverter composed = converter.compose(identity); + + assertEquals(3.0, composed.convert(0.0), "Identity composition should not change the transformation"); + assertEquals(7.0, composed.convert(2.0), "Identity composition should behave like the original"); + } + + @Test + void testLargeInputs() { + double largeValue = 1e6; + assertEquals(2.0 * largeValue + 3.0, converter.convert(largeValue), + "Should handle large input values without overflow"); } } From cedfe111ce7bb2c4fd8e26c851a2b50578431e64 Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Sun, 20 Oct 2024 19:43:07 +0530 Subject: [PATCH 2/4] Fix --- .../conversions/AffineConverterTest.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/test/java/com/thealgorithms/conversions/AffineConverterTest.java b/src/test/java/com/thealgorithms/conversions/AffineConverterTest.java index 5a65609d63cb..47eea139f424 100644 --- a/src/test/java/com/thealgorithms/conversions/AffineConverterTest.java +++ b/src/test/java/com/thealgorithms/conversions/AffineConverterTest.java @@ -23,16 +23,13 @@ void testConstructorWithValidValues() { @Test void testConstructorWithInvalidValues() { - assertThrows(IllegalArgumentException.class, - () -> new AffineConverter(Double.NaN, 3.0), - "Constructor should throw IllegalArgumentException for NaN slope"); + assertThrows(IllegalArgumentException.class, () -> new AffineConverter(Double.NaN, 3.0), "Constructor should throw IllegalArgumentException for NaN slope"); } @Test void testConvertWithNegativeValues() { assertEquals(-1.0, converter.convert(-2.0), "Negative input should convert correctly"); - assertEquals(-3.0, new AffineConverter(-1.0, -1.0).convert(2.0), - "Slope and intercept can be negative"); + assertEquals(-3.0, new AffineConverter(-1.0, -1.0).convert(2.0), "Slope and intercept can be negative"); } @Test @@ -51,8 +48,7 @@ void testInvert() { @Test void testInvertWithZeroSlope() { AffineConverter zeroSlopeConverter = new AffineConverter(0.0, 3.0); - assertThrows(AssertionError.class, zeroSlopeConverter::invert, - "Invert should throw AssertionError when slope is zero"); + assertThrows(AssertionError.class, zeroSlopeConverter::invert, "Invert should throw AssertionError when slope is zero"); } @Test @@ -68,7 +64,7 @@ void testCompose() { void testMultipleCompositions() { AffineConverter c1 = new AffineConverter(2.0, 1.0); AffineConverter c2 = new AffineConverter(3.0, -2.0); - AffineConverter c3 = c1.compose(c2); // (2x + 1) ∘ (3x - 2) => 6x - 1 + AffineConverter c3 = c1.compose(c2); // (2x + 1) ∘ (3x - 2) => 6x - 1 assertEquals(-3.0, c3.convert(0.0), "Composed transformation should return -3.0 at 0.0"); assertEquals(3.0, c3.convert(1.0), "Composed transformation should return 3.0 at 1.0"); @@ -86,7 +82,6 @@ void testIdentityComposition() { @Test void testLargeInputs() { double largeValue = 1e6; - assertEquals(2.0 * largeValue + 3.0, converter.convert(largeValue), - "Should handle large input values without overflow"); + assertEquals(2.0 * largeValue + 3.0, converter.convert(largeValue), "Should handle large input values without overflow"); } } From efefd656eedba6bd2f913baaeeb021d63fd198f5 Mon Sep 17 00:00:00 2001 From: Hardvan Date: Sat, 26 Oct 2024 10:10:47 +0000 Subject: [PATCH 3/4] Update directory --- DIRECTORY.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 10922d761952..a044f6a189a5 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -320,6 +320,7 @@ * [BresenhamLine](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/geometry/BresenhamLine.java) * [ConvexHull](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/geometry/ConvexHull.java) * [GrahamScan](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/geometry/GrahamScan.java) + * [MidpointEllipse](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/geometry/MidpointEllipse.java) * [Point](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/geometry/Point.java) * graph * [StronglyConnectedComponentOptimized](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/graph/StronglyConnectedComponentOptimized.java) @@ -360,6 +361,7 @@ * [Average](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/Average.java) * [BinaryPow](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/BinaryPow.java) * [BinomialCoefficient](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/BinomialCoefficient.java) + * [CatalanNumbers](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/CatalanNumbers.java) * [Ceil](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/Ceil.java) * [ChineseRemainderTheorem](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java) * [CircularConvolutionFFT](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/CircularConvolutionFFT.java) @@ -967,6 +969,7 @@ * [BresenhamLineTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/geometry/BresenhamLineTest.java) * [ConvexHullTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/geometry/ConvexHullTest.java) * [GrahamScanTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/geometry/GrahamScanTest.java) + * [MidpointEllipseTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/geometry/MidpointEllipseTest.java) * graph * [StronglyConnectedComponentOptimizedTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/graph/StronglyConnectedComponentOptimizedTest.java) * greedyalgorithms @@ -1003,6 +1006,7 @@ * [AverageTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/AverageTest.java) * [BinaryPowTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/BinaryPowTest.java) * [BinomialCoefficientTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/BinomialCoefficientTest.java) + * [CatalanNumbersTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/CatalanNumbersTest.java) * [CeilTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/CeilTest.java) * [ChineseRemainderTheoremTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java) * [CollatzConjectureTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/CollatzConjectureTest.java) From 08fefd580208f4b853461fad62eeecad7f6b78f6 Mon Sep 17 00:00:00 2001 From: siriak Date: Sat, 26 Oct 2024 11:54:09 +0000 Subject: [PATCH 4/4] Update directory --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index a044f6a189a5..2aaa29460f8b 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -320,6 +320,7 @@ * [BresenhamLine](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/geometry/BresenhamLine.java) * [ConvexHull](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/geometry/ConvexHull.java) * [GrahamScan](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/geometry/GrahamScan.java) + * [MidpointCircle](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/geometry/MidpointCircle.java) * [MidpointEllipse](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/geometry/MidpointEllipse.java) * [Point](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/geometry/Point.java) * graph @@ -969,6 +970,7 @@ * [BresenhamLineTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/geometry/BresenhamLineTest.java) * [ConvexHullTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/geometry/ConvexHullTest.java) * [GrahamScanTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/geometry/GrahamScanTest.java) + * [MidpointCircleTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/geometry/MidpointCircleTest.java) * [MidpointEllipseTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/geometry/MidpointEllipseTest.java) * graph * [StronglyConnectedComponentOptimizedTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/graph/StronglyConnectedComponentOptimizedTest.java)