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 017package jet.runtime; 018 019public 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}