diff --git a/src/main/java/com/thealgorithms/bitmanipulation/BitSwap.java b/src/main/java/com/thealgorithms/bitmanipulation/BitSwap.java index 40b3097b1276..d8c207567ba6 100644 --- a/src/main/java/com/thealgorithms/bitmanipulation/BitSwap.java +++ b/src/main/java/com/thealgorithms/bitmanipulation/BitSwap.java @@ -1,12 +1,27 @@ package com.thealgorithms.bitmanipulation; +/** + * Utility class for performing bit-swapping operations on integers. + * This class cannot be instantiated. + */ public final class BitSwap { private BitSwap() { } - /* - * @brief Swaps the bits at the position posA and posB from data + + /** + * Swaps two bits at specified positions in an integer. + * + * @param data The input integer whose bits need to be swapped + * @param posA The position of the first bit (0-based, from least significant) + * @param posB The position of the second bit (0-based, from least significant) + * @return The modified value with swapped bits + * @throws IllegalArgumentException if either position is negative or ≥ 32 */ public static int bitSwap(int data, final int posA, final int posB) { + if (posA < 0 || posA >= Integer.SIZE || posB < 0 || posB >= Integer.SIZE) { + throw new IllegalArgumentException("Bit positions must be between 0 and 31"); + } + if (SingleBitOperations.getBit(data, posA) != SingleBitOperations.getBit(data, posB)) { data ^= (1 << posA) ^ (1 << posB); } diff --git a/src/test/java/com/thealgorithms/bitmanipulation/BitSwapTest.java b/src/test/java/com/thealgorithms/bitmanipulation/BitSwapTest.java index 40de770e0c66..9d888d056453 100644 --- a/src/test/java/com/thealgorithms/bitmanipulation/BitSwapTest.java +++ b/src/test/java/com/thealgorithms/bitmanipulation/BitSwapTest.java @@ -1,13 +1,62 @@ package com.thealgorithms.bitmanipulation; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; -import org.junit.jupiter.api.Test; -public class BitSwapTest { - @Test - void testHighestSetBit() { - assertEquals(3, BitSwap.bitSwap(3, 0, 1)); - assertEquals(5, BitSwap.bitSwap(6, 0, 1)); - assertEquals(7, BitSwap.bitSwap(7, 1, 1)); +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class BitSwapTest { + + @ParameterizedTest(name = "Additional cases: data={0}, posA={1}, posB={2} -> expected={3}") + @MethodSource("provideAdditionalCases") + void testAdditionalCases(int data, int posA, int posB, int expected) { + assertEquals(expected, BitSwap.bitSwap(data, posA, posB)); + } + + @ParameterizedTest(name = "Swap different bits: data={0}, posA={1}, posB={2} -> expected={3}") + @MethodSource("provideDifferentBitsCases") + void swapDifferentBits(int data, int posA, int posB, int expected) { + assertEquals(expected, BitSwap.bitSwap(data, posA, posB)); + } + + @ParameterizedTest(name = "Swap same bits: data={0}, posA={1}, posB={2} should not change") + @MethodSource("provideSameBitsCases") + void swapSameBits(int data, int posA, int posB) { + assertEquals(data, BitSwap.bitSwap(data, posA, posB)); + } + + @ParameterizedTest(name = "Edge cases: data={0}, posA={1}, posB={2} -> expected={3}") + @MethodSource("provideEdgeCases") + void testEdgeCases(int data, int posA, int posB, int expected) { + assertEquals(expected, BitSwap.bitSwap(data, posA, posB)); + } + + @ParameterizedTest(name = "Invalid positions: data={0}, posA={1}, posB={2} should throw") + @MethodSource("provideInvalidPositions") + void invalidPositionThrowsException(int data, int posA, int posB) { + assertThrows(IllegalArgumentException.class, () -> BitSwap.bitSwap(data, posA, posB)); + } + + static Stream provideAdditionalCases() { + return Stream.of(Arguments.of(3, 0, 1, 3), Arguments.of(6, 0, 1, 5), Arguments.of(7, 1, 1, 7)); + } + + static Stream provideDifferentBitsCases() { + return Stream.of(Arguments.of(0b01, 0, 1, 0b10)); + } + + static Stream provideSameBitsCases() { + return Stream.of(Arguments.of(0b111, 0, 2), Arguments.of(0b0, 1, 3), Arguments.of(0b1010, 1, 3), Arguments.of(-1, 5, 5)); + } + + static Stream provideEdgeCases() { + return Stream.of(Arguments.of(Integer.MIN_VALUE, 31, 0, 1), Arguments.of(0, 0, 31, 0)); + } + + static Stream provideInvalidPositions() { + return Stream.of(Arguments.of(0, -1, 0), Arguments.of(0, 0, 32), Arguments.of(0, -5, 33), Arguments.of(0, Integer.MIN_VALUE, Integer.MAX_VALUE)); } }