From aea8f3bcee9523df5f0a8d8a4cabc8084b667797 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 20 Jun 2013 21:04:42 +0400 Subject: [PATCH] Fix and test ProgressionUtil Arithmetical modulo implementation was incorrect (-10 mod 1 == 0, but was 1) --- .../jetbrains/jet/ProgressionUtilTest.java | 96 +++++++++++++++++++ runtime/src/jet/runtime/ProgressionUtil.java | 6 +- 2 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 compiler/tests/org/jetbrains/jet/ProgressionUtilTest.java diff --git a/compiler/tests/org/jetbrains/jet/ProgressionUtilTest.java b/compiler/tests/org/jetbrains/jet/ProgressionUtilTest.java new file mode 100644 index 00000000000..d03eff40fc5 --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/ProgressionUtilTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet; + +import jet.runtime.ProgressionUtil; +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; + +public class ProgressionUtilTest { + private static final int MAX = Integer.MAX_VALUE; + private static final int MIN = Integer.MIN_VALUE; + + private static void doTest(int start, int end, int increment, int expected) { + int actualInt = ProgressionUtil.getProgressionFinalElement(start, end, increment); + assertEquals(expected, actualInt); + + long actualLong = ProgressionUtil.getProgressionFinalElement((long) start, (long) end, (long) increment); + assertEquals(expected, actualLong); + } + + private static final int[] INTERESTING = new int[]{ MIN, MIN / 2, -239, -23, -1, 0, 1, 42, 239, MAX / 2, MAX }; + + @Test + public void testGetFinalElement() { + // start == end + for (int x : INTERESTING) { + for (int increment : INTERESTING) if (increment != 0) { + doTest(x, x, increment, x); + } + } + + // increment == 1 + for (int start = 0; start < INTERESTING.length; start++) { + for (int end = start; end < INTERESTING.length; end++) { + doTest(INTERESTING[start], INTERESTING[end], 1, INTERESTING[end]); + } + } + + // increment == -1 + for (int end = 0; end < INTERESTING.length; end++) { + for (int start = end; start < INTERESTING.length; start++) { + doTest(INTERESTING[start], INTERESTING[end], -1, INTERESTING[end]); + } + } + + // end == MAX + doTest(0, MAX, MAX, MAX); + doTest(0, MAX, MAX / 2, MAX - 1); + doTest(MIN + 1, MAX, MAX, MAX); + doTest(MAX - 7, MAX, 3, MAX - 1); + doTest(MAX - 7, MAX, MAX, MAX - 7); + + // end == MIN + doTest(0, MIN, MIN, MIN); + doTest(0, MIN, MIN / 2, MIN); + doTest(MAX, MIN, MIN, -1); + doTest(MIN + 7, MIN, -3, MIN + 1); + doTest(MIN + 7, MIN, MIN, MIN + 7); + + // Small tests + for (int start = -10; start < 10; start++) { + for (int end = -10; end < 10; end++) { + for (int increment = -20; increment < 20; increment++) { + // Cut down incorrect test data + if (increment == 0) continue; + if ((increment > 0) != (start <= end)) continue; + + // Iterate over the progression and obtain the expected result + int x = start; + while (true) { + int next = x + increment; + if (next < Math.min(start, end) || next > Math.max(start, end)) break; + x = next; + } + + doTest(start, end, increment, x); + } + } + } + } +} diff --git a/runtime/src/jet/runtime/ProgressionUtil.java b/runtime/src/jet/runtime/ProgressionUtil.java index a03226a82ce..876262c3e32 100644 --- a/runtime/src/jet/runtime/ProgressionUtil.java +++ b/runtime/src/jet/runtime/ProgressionUtil.java @@ -22,11 +22,13 @@ public class ProgressionUtil { // a mod b (in arithmetical sense) private static int mod(int a, int b) { - return a >= 0 ? a % b : a % b + b; + int mod = a % b; + return mod >= 0 ? mod : mod + b; } private static long mod(long a, long b) { - return a >= 0 ? a % b : a % b + b; + long mod = a % b; + return mod >= 0 ? mod : mod + b; } // (a - b) mod c