Skip to content

Commit 657d49a

Browse files
Copilotriccardobl
andauthored
Rename FastMath.toMultipleOf to alignToPowerOfTwo and provide generic implementation (#2606)
* Initial plan * Rename toMultipleOf to alignToPowerOfTwo and add generic toMultipleOf implementation Co-authored-by: riccardobl <4943530+riccardobl@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: riccardobl <4943530+riccardobl@users.noreply.github.com>
1 parent 80015d1 commit 657d49a

3 files changed

Lines changed: 112 additions & 4 deletions

File tree

jme3-core/src/main/java/com/jme3/math/FastMath.java

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,10 +1203,44 @@ public static float unInterpolateLinear(float value, float min, float max) {
12031203
}
12041204

12051205
/**
1206-
* Round n to a multiple of p
1206+
* Align n to a multiple of p, where p must be a power of two.
1207+
* This is an optimized version that uses bitwise operations.
1208+
*
1209+
* @param n the value to align
1210+
* @param p the alignment value (must be a power of two)
1211+
* @return the smallest value greater than or equal to n that is a multiple of p
1212+
* @throws IllegalArgumentException if p is not a power of two
1213+
*/
1214+
public static int alignToPowerOfTwo(int n, int p) {
1215+
if (!isPowerOfTwo(p)) {
1216+
throw new IllegalArgumentException("p must be a power of two, got: " + p);
1217+
}
1218+
return ((n - 1) | (p - 1)) + 1;
1219+
}
1220+
1221+
/**
1222+
* Round n up to the nearest multiple of p.
1223+
* This works for any positive integer p.
1224+
*
1225+
* @param n the value to round
1226+
* @param p the multiple (must be positive)
1227+
* @return the smallest value greater than or equal to n that is a multiple of p
1228+
* @throws IllegalArgumentException if p is not positive
12071229
*/
12081230
public static int toMultipleOf(int n, int p) {
1209-
return ((n - 1) | (p - 1)) + 1;
1231+
if (p <= 0) {
1232+
throw new IllegalArgumentException("p must be positive, got: " + p);
1233+
}
1234+
// For powers of two, use the optimized version
1235+
if (isPowerOfTwo(p)) {
1236+
return ((n - 1) | (p - 1)) + 1;
1237+
}
1238+
// Generic implementation for any positive integer
1239+
int remainder = n % p;
1240+
if (remainder == 0) {
1241+
return n;
1242+
}
1243+
return n + (p - remainder);
12101244
}
12111245

12121246
}

jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/BufferLayout.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,11 @@ public int getBasicAlignment(Object o) {
120120
* @param pos
121121
* the position to align
122122
* @param basicAlignment
123-
* the basic alignment
123+
* the basic alignment (must be a power of two)
124124
* @return the aligned position
125125
*/
126126
public int align(int pos, int basicAlignment) {
127-
return pos==0?pos:FastMath.toMultipleOf(pos, basicAlignment);
127+
return pos==0?pos:FastMath.alignToPowerOfTwo(pos, basicAlignment);
128128
}
129129

130130
/**

jme3-core/src/test/java/com/jme3/math/FastMathTest.java

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,4 +855,78 @@ public void testSphericalToCartesianZ() {
855855
assertEquals(0.0f, retval.getY(), 0.0f);
856856
assertEquals(0.0f, retval.getZ(), 0.0f);
857857
}
858+
859+
@Test
860+
public void testAlignToPowerOfTwo() {
861+
// Test with various power-of-two values
862+
assertEquals(8, FastMath.alignToPowerOfTwo(5, 4));
863+
assertEquals(8, FastMath.alignToPowerOfTwo(8, 4));
864+
assertEquals(16, FastMath.alignToPowerOfTwo(15, 16));
865+
assertEquals(16, FastMath.alignToPowerOfTwo(16, 16));
866+
assertEquals(32, FastMath.alignToPowerOfTwo(17, 16));
867+
assertEquals(1, FastMath.alignToPowerOfTwo(1, 1));
868+
assertEquals(2, FastMath.alignToPowerOfTwo(2, 2));
869+
assertEquals(4, FastMath.alignToPowerOfTwo(3, 4));
870+
assertEquals(64, FastMath.alignToPowerOfTwo(50, 64));
871+
assertEquals(128, FastMath.alignToPowerOfTwo(100, 128));
872+
873+
// Test edge cases
874+
assertEquals(256, FastMath.alignToPowerOfTwo(256, 256));
875+
assertEquals(512, FastMath.alignToPowerOfTwo(257, 256));
876+
877+
// Test that it throws for non-power-of-two values
878+
try {
879+
FastMath.alignToPowerOfTwo(10, 3);
880+
fail("Expected IllegalArgumentException for non-power-of-two");
881+
} catch (IllegalArgumentException e) {
882+
// Expected
883+
}
884+
885+
try {
886+
FastMath.alignToPowerOfTwo(10, 6);
887+
fail("Expected IllegalArgumentException for non-power-of-two");
888+
} catch (IllegalArgumentException e) {
889+
// Expected
890+
}
891+
}
892+
893+
@Test
894+
public void testToMultipleOf() {
895+
// Test with various values including non-powers-of-two
896+
assertEquals(6, FastMath.toMultipleOf(5, 3));
897+
assertEquals(6, FastMath.toMultipleOf(6, 3));
898+
assertEquals(9, FastMath.toMultipleOf(7, 3));
899+
assertEquals(10, FastMath.toMultipleOf(10, 5));
900+
assertEquals(15, FastMath.toMultipleOf(11, 5));
901+
assertEquals(7, FastMath.toMultipleOf(5, 7));
902+
assertEquals(7, FastMath.toMultipleOf(7, 7));
903+
assertEquals(14, FastMath.toMultipleOf(8, 7));
904+
905+
// Test with power-of-two values (should work too)
906+
assertEquals(8, FastMath.toMultipleOf(5, 4));
907+
assertEquals(8, FastMath.toMultipleOf(8, 4));
908+
assertEquals(16, FastMath.toMultipleOf(15, 16));
909+
assertEquals(16, FastMath.toMultipleOf(16, 16));
910+
assertEquals(32, FastMath.toMultipleOf(17, 16));
911+
912+
// Test edge cases
913+
assertEquals(1, FastMath.toMultipleOf(1, 1));
914+
assertEquals(100, FastMath.toMultipleOf(100, 100));
915+
assertEquals(200, FastMath.toMultipleOf(101, 100));
916+
917+
// Test that it throws for non-positive values
918+
try {
919+
FastMath.toMultipleOf(10, 0);
920+
fail("Expected IllegalArgumentException for p=0");
921+
} catch (IllegalArgumentException e) {
922+
// Expected
923+
}
924+
925+
try {
926+
FastMath.toMultipleOf(10, -5);
927+
fail("Expected IllegalArgumentException for negative p");
928+
} catch (IllegalArgumentException e) {
929+
// Expected
930+
}
931+
}
858932
}

0 commit comments

Comments
 (0)