package com.robonobo.common.util;
import java.util.Comparator;
/*
* Robonobo Common Utils
* Copyright (C) 2008 Will Morton (macavity@well.com) & Ray Hilton (ray@wirestorm.net)
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*
* This source code file is Copyright 2004 Ray Hilton / Will Morton. All rights reserved.
* Unauthorised duplication of this file is expressly forbidden without prior
* written permission.
*/
public class Modulo implements Comparator<Long> {
long modulus;
/**
* Modulus can be up to and including Integer.MAX_VALUE+1 (2^32), but no
* larger
*/
public Modulo(long mod) {
if (mod < 0)
throw new IllegalArgumentException(
"mod must be non-negative");
modulus = mod;
}
public Modulo(int mod) {
if (mod < 0)
throw new IllegalArgumentException(
"mod must be non-negative");
modulus = (long) mod;
}
// LessThan/MoreThan is fun with modulo numbers;
// If we are doing arithmetic modulo M with a number n,
// then the numbers (n+1)%M to (n+(M/2))%M are greater than n,
// and (n-(M/2)+1)%M to (n-1)%M are less than n
/**
* Like (num1 < num2), but using modulo arithmetic
*/
public boolean lt(long num1, long num2) {
if (num1 < 0 || num2 < 0)
throw new IllegalArgumentException(
"Both arguments must be non-negative");
if (num2 >= (modulus / 2)) {
if ((num1 > (num2 - (modulus / 2))) && (num1 < num2))
return true;
else
return false;
} else {
if ((num1 <= (num2 + (modulus / 2))) && (num1 >= num2))
return false;
else
return true;
}
}
/**
* Like (num1 < num2), but using modulo arithmetic
*/
public boolean lt(int num1, int num2) {
if (num1 < 0 || num2 < 0)
throw new IllegalArgumentException(
"Both arguments must be non-negative");
return lt((long) num1, (long) num2);
}
/**
* Like (num1 <= num2), but using modulo arithmetic
*/
public boolean lte(long num1, long num2) {
if (num1 < 0 || num2 < 0)
throw new IllegalArgumentException(
"Both arguments must be non-negative");
return (num1 == num2) || lt(num1, num2);
}
/**
* Like (num1 <= num2), but using modulo arithmetic
*/
public boolean lte(int num1, int num2) {
if (num1 < 0 || num2 < 0)
throw new IllegalArgumentException(
"Both arguments must be non-negative");
return lte((long) num1, (long) num2);
}
/**
* Like (num1 > num2), but using modulo arithmetic
*/
public boolean gt(long num1, long num2) {
if (num1 < 0 || num2 < 0)
throw new IllegalArgumentException(
"Both arguments must be non-negative");
return lt(num2, num1);
}
/**
* Like (num1 > num2), but using modulo arithmetic
*/
public boolean gt(int num1, int num2) {
if (num1 < 0 || num2 < 0)
throw new IllegalArgumentException(
"Both arguments must be non-negative");
return gt((long) num1, (long) num2);
}
/**
* Like (num1 >= num2), but using modulo arithmetic
*/
public boolean gte(long num1, long num2) {
if (num1 < 0 || num2 < 0)
throw new IllegalArgumentException(
"Both arguments must be non-negative");
return (num1 == num2) || lt(num2, num1);
}
/**
* Like (num1 >= num2), but using modulo arithmetic
*/
public boolean gte(int num1, int num2) {
if (num1 < 0 || num2 < 0)
throw new IllegalArgumentException(
"Both arguments must be non-negative");
return gte((long) num1, (long) num2);
}
/**
* Like (num1 + num2), but using modulo arithmetic
*/
public long add(long num1, long num2) {
if (num1 < 0 || num2 < 0)
throw new IllegalArgumentException(
"Both arguments must be non-negative (" + num1 + ", "
+ num2 + ")");
// We have to cast here in case it overflows internally,
// eg when modulus == Uint32.MaxValue such as in TCP/S-EON
return (long) ((num1 + num2) % modulus);
}
/**
* Like (num1 + num2), but using modulo arithmetic
*/
public int add(int num1, int num2) {
return (int) add((long) num1, (long) num2);
}
/**
* Like (num - toSubtract), but using modulo arithmetic
*/
public long sub(long num, long toSubtract) {
if (num < 0)
throw new IllegalArgumentException("Argument must be non-negative");
if (num >= toSubtract) {
return (num - toSubtract);
} else {
return (long) (modulus - (toSubtract - num));
}
}
/**
* Like (num - toSubtract), but using modulo arithmetic
*/
public int sub(int num, int toSubtract) {
return (int) sub((long) num, (long) toSubtract);
}
/**
* Compares the two values using modulo arithmetic
*/
public int compare(Long l1, Long l2) {
if(lt(l1, l2))
return -1;
if(gt(l1, l2))
return 1;
return 0;
}
public long getModulus() {
return modulus;
}
}