diff --git a/src/main/java/com/thealgorithms/physics/Relativity.java b/src/main/java/com/thealgorithms/physics/Relativity.java new file mode 100644 index 000000000000..ed823c2cc879 --- /dev/null +++ b/src/main/java/com/thealgorithms/physics/Relativity.java @@ -0,0 +1,81 @@ +package com.thealgorithms.physics; + +/** + * Implements relativity theory formulae. + * Provides simple static methods to calculate length contraction and time dilation + * in the laboratory frame with respect to the object's own frame, and velocity + * with respect to the moving frame. + * + * @see Wikipedia + */ +public final class Relativity { + + /* Speed of light in m s^-1 */ + public static final double SPEED_OF_LIGHT = 299792458.0; + + /** + * Private constructor to prevent instantiation of this utility class. + */ + private Relativity() { + } + + /** + * Calculates the gamma parameter that is of paramount importance in relativity + * theory. It is a dimensionless parameter that is equal to 1 for zero velocity + * but tends to infinity when velocity approaches the speed of light. + * + * @param v The velocity (m/s). + * @return The value of gamma parameter. + */ + public static double gamma(double v) { + if (Math.abs(v) >= SPEED_OF_LIGHT) { + throw new IllegalArgumentException("Speed must be lower than the speed of light"); + } + return 1.0 / Math.sqrt(1 - v * v / (SPEED_OF_LIGHT * SPEED_OF_LIGHT)); + } + + /** + * Calculates the length of an object in the moving frame. + * + * @param length The length of an object in its own frame (m). + * @param v The velocity of the object (m/s). + * @return The length of an object in the laboratory frame (m). + */ + public static double lengthContraction(double length, double v) { + if (length < 0) { + throw new IllegalArgumentException("Length must be non-negative"); + } + return length / gamma(v); + } + + /** + * Calculates the time that has passed in the moving frame. + * + * @param length The time that has passed in the object's own frame (s). + * @param v The velocity of the object (m/s). + * @return The time that has passed in the laboratory frame (s). + */ + public static double timeDilation(double time, double v) { + if (time < 0) { + throw new IllegalArgumentException("Time must be non-negative"); + } + return time * gamma(v); + } + + /** + * Calculates the velocity with respect to the moving frame. + * + * @param v1 The velocity of the object with respect to laboratory frame (m/s). + * @param v The velocity of the moving frame (m/s). + * @return The velocity with respect to the moving frame (m/s). + */ + public static double velocityAddition(double v1, double v) { + if (Math.abs(v1) > SPEED_OF_LIGHT) { + throw new IllegalArgumentException("Speed must not exceed the speed of light"); + } + if (Math.abs(v) >= SPEED_OF_LIGHT) { + throw new IllegalArgumentException("Frame speed must be lower than the speed of light"); + } + return (v1 - v) / (1 - v1 * v / (SPEED_OF_LIGHT * SPEED_OF_LIGHT)); + } +} diff --git a/src/test/java/com/thealgorithms/physics/RelativityTest.java b/src/test/java/com/thealgorithms/physics/RelativityTest.java new file mode 100644 index 000000000000..44c17bdbd40f --- /dev/null +++ b/src/test/java/com/thealgorithms/physics/RelativityTest.java @@ -0,0 +1,73 @@ +package com.thealgorithms.physics; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +/** + * Unit tests for the Relativity utility class. + */ +final class RelativityTest { + + // A small tolerance (delta) for comparing floating-point numbers + private static final double DELTA = 1e-6; + private static final double C = Relativity.SPEED_OF_LIGHT; + + @Test + @DisplayName("Test the gamma parameter") + void testGamma() { + double myGamma = Relativity.gamma(0.6 * C); + assertEquals(1.25, myGamma, DELTA); + } + + @Test + @DisplayName("Test the length contraction") + void testLengthContraction() { + double myLength = Relativity.lengthContraction(5.0, 0.8 * C); + assertEquals(3.0, myLength, DELTA); + } + + @Test + @DisplayName("Test the time dilation") + void testTimeDilation() { + double myTime = Relativity.timeDilation(4.0, 0.6 * C); + assertEquals(5.0, myTime, DELTA); + } + + @Test + @DisplayName("Test the velocity addition in the same direction") + void testVelocityAdditionSameDirection() { + double myVelocity = Relativity.velocityAddition(0.8 * C, 0.75 * C); + assertEquals(0.125 * C, myVelocity, DELTA); + } + + @Test + @DisplayName("Test the velocity addition in different directions") + void testVelocityAdditionDifferentDirections() { + double myVelocity = Relativity.velocityAddition(0.8 * C, -0.75 * C); + assertEquals(0.96875 * C, myVelocity, DELTA); + } + + @Test + @DisplayName("Test the velocity addition with the speed of light") + void testVelocityAdditionWithSpeedOfLight() { + double myVelocity = Relativity.velocityAddition(C, 0.7 * C); + assertEquals(C, myVelocity, DELTA); + } + + @Test + @DisplayName("Test invalid inputs throw exception") + void testInvalidOrbitalVelocityInputs() { + assertThrows(IllegalArgumentException.class, () -> Relativity.gamma(1.2 * C)); + assertThrows(IllegalArgumentException.class, () -> Relativity.gamma(-C)); + assertThrows(IllegalArgumentException.class, () -> Relativity.lengthContraction(-1.0, 0.6 * C)); + assertThrows(IllegalArgumentException.class, () -> Relativity.lengthContraction(1.0, 1.5 * C)); + assertThrows(IllegalArgumentException.class, () -> Relativity.timeDilation(-5.0, -0.8 * C)); + assertThrows(IllegalArgumentException.class, () -> Relativity.timeDilation(5.0, C)); + assertThrows(IllegalArgumentException.class, () -> Relativity.velocityAddition(0.3 * C, -C)); + assertThrows(IllegalArgumentException.class, () -> Relativity.velocityAddition(1.4 * C, 0.2 * C)); + assertThrows(IllegalArgumentException.class, () -> Relativity.velocityAddition(-0.4 * C, 1.2 * C)); + } +}