001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package jet.runtime;
018
019 public class ProgressionUtil {
020 private ProgressionUtil() {
021 }
022
023 // a mod b (in arithmetical sense)
024 private static int mod(int a, int b) {
025 int mod = a % b;
026 return mod >= 0 ? mod : mod + b;
027 }
028
029 private static long mod(long a, long b) {
030 long mod = a % b;
031 return mod >= 0 ? mod : mod + b;
032 }
033
034 // (a - b) mod c
035 private static int differenceModulo(int a, int b, int c) {
036 return mod(mod(a, c) - mod(b, c), c);
037 }
038
039 private static long differenceModulo(long a, long b, long c) {
040 return mod(mod(a, c) - mod(b, c), c);
041 }
042
043
044 /**
045 * Calculates the final element of a bounded arithmetic progression, i.e. the last element of the progression which is in the range
046 * from {@code start} to {@code end} in case of a positive {@code increment}, or from {@code end} to {@code start} in case of a negative
047 * increment.
048 *
049 * <p>No validation on passed parameters is performed. The given parameters should satisfy the condition: either
050 * {@code increment > 0} and {@code start <= end}, or {@code increment < 0} and {@code start >= end}.
051 * @param start first element of the progression
052 * @param end ending bound for the progression
053 * @param increment increment, or difference of successive elements in the progression
054 * @return the final element of the progression
055 */
056 public static int getProgressionFinalElement(int start, int end, int increment) {
057 if (increment > 0) {
058 return end - differenceModulo(end, start, increment);
059 }
060 else {
061 return end + differenceModulo(start, end, -increment);
062 }
063 }
064
065 /**
066 * Calculates the final element of a bounded arithmetic progression, i.e. the last element of the progression which is in the range
067 * from {@code start} to {@code end} in case of a positive {@code increment}, or from {@code end} to {@code start} in case of a negative
068 * increment.
069 *
070 * <p>No validation on passed parameters is performed. The given parameters should satisfy the condition: either
071 * {@code increment > 0} and {@code start <= end}, or {@code increment < 0} and {@code start >= end}.
072 * @param start first element of the progression
073 * @param end ending bound for the progression
074 * @param increment increment, or difference of successive elements in the progression
075 * @return the final element of the progression
076 */
077 public static long getProgressionFinalElement(long start, long end, long increment) {
078 if (increment > 0) {
079 return end - differenceModulo(end, start, increment);
080 }
081 else {
082 return end + differenceModulo(start, end, -increment);
083 }
084 }
085 }