net.sandius.rembulan.LuaMathOperators Maven / Gradle / Ivy
/*
* Copyright 2016 Miroslav Janíček
*
* 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 net.sandius.rembulan;
/**
* A collection of static methods for performing the equivalents of Lua's arithmetic,
* bitwise and numerical comparison operations.
*
* This class and its methods exploits the isomorphism between Lua integers and
* Java {@code long} on the one hand, and between Lua floats and Java {@code double}
* on the other.
*
* For each operation, there are as many variants in the form of a static method
* as there are valid type combinations. While all arithmetic operations
* are defined in two variants (for two {@code long}s and two {@code double}s, e.g.
* {@link #idiv(long, long)} and {@link #idiv(double, double)}), bitwise operations
* have single variants (taking two {@code long}s, e.g. {@link #band(long, long)}),
* and numerical comparison operations have four variants (for argument type combination).
*
* It is the task of a Lua implementation to select the appropriate method and
* supply it with the required values; however, note that the method selection is well-behaved
* under the type conversion rules of the Java programming language.
*/
public final class LuaMathOperators {
private LuaMathOperators() {
// not to be instantiated or extended
}
// Arithmetic operators
/**
* Returns the result of the addition of two {@code long}s, equivalent to the addition
* of two integers in Lua.
*
* @param a first addend
* @param b second addend
* @return the value of the Lua expression {@code (a + b)},
* where {@code a} and {@code b} are Lua integers
*/
public static long add(long a, long b) {
return a + b;
}
/**
* Returns the result of the addition of two {@code double}s, equivalent to the addition
* of two floats in Lua.
*
* @param a first addend
* @param b second addend
* @return the value of the Lua expression {@code (a + b)},
* where {@code a} and {@code b} are Lua floats
*/
public static double add(double a, double b) {
return a + b;
}
/**
* Returns the result of the subtraction of two {@code long}s, equivalent to the subtraction
* of two integers in Lua.
*
* @param a the minuend
* @param b the subtrahend
* @return the value of the Lua expression {@code (a - b)},
* where {@code a} and {@code b} are Lua integers
*/
public static long sub(long a, long b) {
return a - b;
}
/**
* Returns the result of the subtraction of two {@code double}s, equivalent to the subtraction
* of two floats in Lua.
*
* @param a the minuend
* @param b the subtrahend
* @return the value of the Lua expression {@code (a - b)},
* where {@code a} and {@code b} are Lua floats
*/
public static double sub(double a, double b) {
return a - b;
}
/**
* Returns the result of the multiplication of two {@code long}s, equivalent to
* the multiplication of two integers in Lua.
*
* @param a first factor
* @param b second factor
* @return the value of the Lua expression {@code (a * b)},
* where {@code a} and {@code b} are Lua integers
*/
public static long mul(long a, long b) {
return a * b;
}
/**
* Returns the result of the multiplication of two {@code double}s, equivalent to
* the multiplication of two floats in Lua.
*
* @param a first factor
* @param b second factor
* @return the value of the Lua expression {@code (a * b)},
* where {@code a} and {@code b} are Lua floats
*/
public static double mul(double a, double b) {
return a * b;
}
/**
* Returns the result of the division of two {@code long}s, equivalent to the float
* division of two integers in Lua. The result is always a {@code double}; when {@code b}
* is zero, the result is NaN.
*
* Note that this behaviour differs from the standard Java integer division.
*
* @param a the dividend
* @param b the divisor
* @return the value of the Lua expression {@code (a / b)},
* where {@code a} and {@code b} are Lua integers
*/
public static double div(long a, long b) {
return ((double) a) / ((double) b);
}
/**
* Returns the result of the division of two {@code double}s, equivalent to the float
* division of two floats in Lua.
*
* @param a the dividend
* @param b the divisor
* @return the value of the Lua expression {@code (a / b)},
* where {@code a} and {@code b} are Lua floats
*/
public static double div(double a, double b) {
return a / b;
}
/**
* Returns the floor modulus of two {@code long}s, equivalent to the modulus
* of two integers in Lua.
*
* Note that in Lua,
*
*
* Modulo is defined as the remainder of a division that rounds the quotient
* towards minus infinity (floor division).
*
*
* This definition is not equivalent to the standard Java definition of modulo
* (which is the remainder of a division rounding toward zero).
*
* @param a the dividend
* @param b the divisor
* @return the value of the Lua expression {@code (a % b)},
* where {@code a} and {@code b} are Lua integers
*
* @throws ArithmeticException if {@code b} is zero
*/
public static long mod(long a, long b) {
// Note: in JDK 8+, Math.floorMod could be used
if (b == 0) throw new ArithmeticException("attempt to perform 'n%0'");
else return a - b * (long) Math.floor((double) a / (double) b);
}
/**
* Returns the floor modulus of two {@code double}s, equivalent to the modulus
* of two floats in Lua.
*
* Note that in Lua,
*
*
* Modulo is defined as the remainder of a division that rounds the quotient
* towards minus infinity (floor division).
*
*
* This definition is not equivalent to the standard Java definition of modulo
* (which is the remainder of a division rounding toward zero).
*
* @param a the dividend
* @param b the divisor
* @return the value of the Lua expression {@code (a % b)},
* where {@code a} and {@code b} are Lua floats
*/
public static double mod(double a, double b) {
return b != 0 ? a - b * Math.floor(a / b) : Double.NaN;
}
/**
* Returns the result of floor division of two {@code long}s, equivalent to the Lua
* floor division of two integers.
*
* In Lua,
*
*
* Floor division (//) is a division that rounds the quotient towards minus infinity,
* that is, the floor of the division of its operands.
*
*
* @param a the dividend
* @param b the divisor
* @return the value of the Lua expression {@code (a // b)}
* where {@code a} and {@code b} are Lua integers
*
* @throws ArithmeticException if {@code b} is zero
*/
public static long idiv(long a, long b) {
if (b == 0) throw new ArithmeticException("attempt to divide by zero");
else {
long q = a / b;
return q * b == a || (a ^ b) >= 0 ? q : q - 1;
}
}
/**
* Returns the result of floor division of two {@code double}s, equivalent to the Lua
* floor division of two floats:
*
* In Lua,
*
*
* Floor division (//) is a division that rounds the quotient towards minus infinity,
* that is, the floor of the division of its operands.
*
*
* @param a the dividend
* @param b the divisor
* @return the value of the Lua expression {@code (a // b)}
* where {@code a} and {@code b} are Lua floats
*/
public static double idiv(double a, double b) {
return Math.floor(a / b);
}
/**
* Returns the result of the exponentiation of two {@code long}s, equivalent to the Lua
* exponentiation of two integers. Note that the resulting value is a {@code double}.
*
* @param a the base
* @param b the exponent
* @return the value of the Lua expression {@code (a ^ b)},
* where {@code a} and {@code b} are Lua integers
*/
public static double pow(long a, long b) {
return Math.pow((double) a, (double) b);
}
/**
* Returns the result of the exponentiation of two {@code double}s, equivalent to Lua
* exponentiation of two floats.
*
* @param a the base
* @param b the exponent
* @return the value of the Lua expression {@code (a ^ b)},
* where {@code a} and {@code b} are Lua floats
*/
public static double pow(double a, double b) {
return Math.pow(a, b);
}
/**
* Returns the result of the (arithmetic) negation of a {@code long}, equivalent to
* the Lua unary minus on an integer.
*
* @param n the operand
* @return the value of the Lua expression {@code (-n)},
* where {@code n} is a Lua integer
*/
public static long unm(long n) {
return -n;
}
/**
* Returns the result of the (arithmetic) negation of a {@code long}, equivalent to
* the Lua unary minus on a float.
*
* @param n the operand
* @return the value of the Lua expression {@code (-n)},
* where {@code n} is a Lua float
*/
public static double unm(double n) {
return -n;
}
// Bitwise operators
/**
* Returns the result of the bitwise AND of two {@code long}s, equivalent to the Lua
* bitwise AND of two integers.
*
* @param a the first operand
* @param b the second operand
* @return the value of the Lua expression {@code (a & b)},
* where {@code a} and {@code b} are Lua integers
*/
public static long band(long a, long b) {
return a & b;
}
/**
* Returns the result of the bitwise OR of two {@code long}s, equivalent to the Lua
* bitwise OR of two integers.
*
* @param a the first operand
* @param b the second operand
* @return the value of the Lua expression {@code (a | b)},
* where {@code a} and {@code b} are Lua integers
*/
public static long bor(long a, long b) {
return a | b;
}
/**
* Returns the result of the bitwise exclusive OR of two {@code long}s,
* equivalent to the Lua bitwise exclusive OR of two integers.
*
* @param a the first operand
* @param b the second operand
* @return the value of the Lua expression {@code (a ~ b)},
* where {@code a} and {@code b} are Lua integers
*/
public static long bxor(long a, long b) {
return a ^ b;
}
/**
* Returns the result of the (bitwise) logical left shift, equivalent to the Lua bitwise
* left shift on two integers. Vacant bits are filled with zeros. When {@code b} is negative,
* the result is equal to the result of a right shift by {@code -b}.
*
* Note that Lua's behaviour differs from Java's {@code <<} operator in that if
* {@code b} is greater than 64, the result is zero, as all bits have been shifted out.
*
* @param a the left-hand side operand
* @param b the right-hand side operand (shift distance)
* @return the value of the Lua expression {@code (a << b)},
* where {@code a} and {@code b} are Lua integers
*/
public static long shl(long a, long b) {
return b < 0 ? shr(a, -b) : (b < 64 ? a << b : 0);
}
/**
* Returns the result of the (bitwise) logical right shift, equivalent to the Lua bitwise
* right shift on two integers. Vacant bits are filled with zeros. When {@code b} is negative,
* the result is equal to the result of a left shift by {@code -b}.
*
* Note that Lua's behaviour differs from Java's {@code >>>} operator in that if
* {@code b} is greater than 64, the result is zero, as all bits have been shifted out.
*
* @param a the left-hand side operand
* @param b the right-hand side operand (shift distance)
* @return the value of the Lua expression {@code (a << b)},
* where {@code a} and {@code b} are Lua integers
*/
public static long shr(long a, long b) {
return b < 0 ? shl(a, -b) : (b < 64 ? a >>> b : 0);
}
/**
* Returns the result of the bitwise unary NOT of a {@code long}, equivalent to the Lua
* bitwise unary NOT on an integer.
*
* @param n the operand
* @return the value of the Lua expression {@code (~b)},
* where {@code n} is a Lua integer
*/
public static long bnot(long n) {
return ~n;
}
// Numerical comparison operators
private static final double MAX_LONG_AS_DOUBLE = (double) Long.MAX_VALUE;
private static final double MIN_LONG_AS_DOUBLE = (double) Long.MIN_VALUE;
/**
* Returns {@code true} iff the {@code double} {@code d} can be represented by
* a {@code long} without the loss of precision, i.e. if {@code ((long) d)}
* and {@code d} denote the same mathematical value.
*
* @param d the {@code double} in question
* @return {@code true} iff {@code d} can be represented by a {@code long}
* without the loss of precision
*/
public static boolean hasExactIntegerRepresentation(double d) {
long l = (long) d;
return (double) l == d && l != Long.MAX_VALUE;
}
/**
* Returns {@code true} iff the {@code long} {@code l} can be represented by
* a {@code double} without the loss of precision, i.e. if {@code ((double) l)}
* and {@code l} denote the same mathematical value.
*
* @param l the {@code long} in question
* @return {@code true} iff {@code l} can be represented by a {@code double}
* without the loss of precision
*/
public static boolean hasExactFloatRepresentation(long l) {
double d = (double) l;
return (long) d == l && l != Long.MAX_VALUE;
}
/**
* Returns {@code true} iff the {@code long}s {@code a} and {@code b} denote
* the same mathematical value. This is equivalent to the Lua numerical equality
* comparison of two integers.
*
* @param a a {@code long}
* @param b a {@code long} to be compared with {@code a} for mathematical equality
* @return {@code true} iff the Lua expression {@code (a == b)},
* where {@code a} and {@code b} are Lua integers,
* would evaluate to (Lua) true
*/
public static boolean eq(long a, long b) {
return a == b;
}
/**
* Returns {@code true} iff the {@code long} {@code a} denotes the same mathematical
* value as the {@code double} {@code b}. This is equivalent to the Lua numerical
* equality comparison of an integer and a float.
*
* @param a a {@code long}
* @param b a {@code double} to be compared with {@code a} for mathematical equality
* @return {@code true} iff the Lua expression {@code (a == b)},
* where {@code a} is a Lua integer and {@code b} is a Lua float,
* would evaluate to (Lua) true
*/
public static boolean eq(long a, double b) {
return hasExactFloatRepresentation(a) && (double) a == b;
}
/**
* Returns {@code true} iff the {@code double} {@code a} denotes the same mathematical
* value as the {@code long} {@code b}. This is equivalent to the Lua numerical equality
* comparison of a float and an integer.
*
* @param a a {@code double}
* @param b a {@code long} to be compared with {@code a} for mathematical equality
* @return {@code true} iff the Lua expression {@code (a == b)},
* where {@code a} is a Lua float and {@code b} is a Lua integer,
* would evaluate to (Lua) true
*/
public static boolean eq(double a, long b) {
return hasExactFloatRepresentation(b) && a == (double) b;
}
/**
* Returns {@code true} iff the {@code double}s {@code a} and {@code b} denote
* the same mathematical value. This is equivalent to the Lua numerical equality
* comparison of two doubles.
*
* @param a a {@code double}
* @param b a {@code double} to be compared with {@code a} for mathematical equality
* @return {@code true} iff the Lua expression {@code (a == b)},
* where {@code a} and {@code b} are Lua floats,
* would evaluate to (Lua) true
*/
public static boolean eq(double a, double b) {
return a == b;
}
/**
* Returns {@code true} iff the mathematical value of the {@code long} {@code a}
* is lesser than the mathematical value of the {@code long} {@code b}. This is equivalent
* to the Lua numerical lesser-than comparison of two integers.
*
* @param a a {@code long}
* @param b a {@code long} to be compared with {@code a}
* @return {@code true} iff the Lua expression {@code (a < b)},
* where {@code a} and {@code b} are Lua integers,
* would evaluate to (Lua) true
*/
public static boolean lt(long a, long b) {
return a < b;
}
/**
* Returns {@code true} iff the mathematical value of the {@code long} {@code a}
* is lesser than the mathematical value of the {@code double} {@code b}. This
* is equivalent to the Lua numerical lesser-than comparison of an integer and a float.
*
* @param a a {@code long}
* @param b a {@code double} to be compared with {@code a}
* @return {@code true} iff the Lua expression {@code (a < b)},
* where {@code a} is a Lua integer and {@code b} is a Lua float,
* would evaluate to (Lua) true
*/
public static boolean lt(long a, double b) {
if (hasExactFloatRepresentation(a)) {
return (double) a < b;
}
else {
return b == b && b > MIN_LONG_AS_DOUBLE && (b >= MAX_LONG_AS_DOUBLE || a < (long) b);
}
}
/**
* Returns {@code true} iff the mathematical value of the {@code double} {@code a}
* is lesser than the mathematical value of the {@code long} {@code b}. This
* is equivalent to the Lua numerical lesser-than comparison of a float and an integer.
*
* @param a a {@code double}
* @param b a {@code long} to be compared with {@code a}
* @return {@code true} iff the Lua expression {@code (a < b)},
* where {@code a} is a Lua float and {@code b} is a Lua integer,
* would evaluate to (Lua) true
*/
public static boolean lt(double a, long b) {
return a == a && !le(b, a);
}
/**
* Returns {@code true} iff the mathematical value of the {@code double} {@code a}
* is lesser than the mathematical value of the {@code double} {@code b}. This
* is equivalent to the Lua numerical lesser-than comparison of two floats.
*
* @param a a {@code double}
* @param b a {@code double} to be compared with {@code a}
* @return {@code true} iff the Lua expression {@code (a < b)},
* where {@code a} and {@code b} are Lua floats,
* would evaluate to (Lua) true
*/
public static boolean lt(double a, double b) {
return a < b;
}
/**
* Returns {@code true} iff the mathematical value of the {@code long} {@code a}
* is lesser than or equal to the mathematical value of the {@code long} {@code b}.
* This is equivalent to the Lua numerical lesser-than-or-equal comparison of
* two integers.
*
* @param a a {@code long}
* @param b a {@code long} to be compared with {@code a}
* @return {@code true} iff the Lua expression {@code (a <= b)},
* where {@code a} and {@code b} are Lua integers,
* would evaluate to (Lua) true
*/
public static boolean le(long a, long b) {
return a <= b;
}
/**
* Returns {@code true} iff the mathematical value of the {@code long} {@code a}
* is lesser than or equal to the mathematical value of the {@code double} {@code b}.
* This is equivalent to the Lua numerical lesser-than-or-equal comparison of
* an integer and a float.
*
* @param a a {@code long}
* @param b a {@code double} to be compared with {@code a}
* @return {@code true} iff the Lua expression {@code (a <= b)},
* where {@code a} is a Lua integer and {@code b} is a Lua float,
* would evaluate to (Lua) true
*/
public static boolean le(long a, double b) {
if (hasExactFloatRepresentation(a)) {
return (double) a <= b;
}
else {
return b == b && b > MIN_LONG_AS_DOUBLE && (b >= MAX_LONG_AS_DOUBLE || a <= (long) b);
}
}
/**
* Returns {@code true} iff the mathematical value of the {@code double} {@code a}
* is lesser than or equal to the mathematical value of the {@code long} {@code b}.
* This is equivalent to the Lua numerical lesser-than-or-equal comparison of
* a float and an integer.
*
* @param a a {@code double}
* @param b a {@code long} to be compared with {@code a}
* @return {@code true} iff the Lua expression {@code (a <= b)},
* where {@code a} is a Lua float and {@code b} is a Lua integer,
* would evaluate to (Lua) true
*/
public static boolean le(double a, long b) {
return a == a && !lt(b, a);
}
/**
* Returns {@code true} iff the mathematical value of the {@code double} {@code a}
* is lesser than or equal to the mathematical value of the {@code double} {@code b}.
* This is equivalent to the Lua numerical lesser-than-or-equal comparison of
* two floats.
*
* @param a a {@code double}
* @param b a {@code double} to be compared with {@code a}
* @return {@code true} iff the Lua expression {@code (a <= b)},
* where {@code a} and {@code b} are Lua floats,
* would evaluate to (Lua) true
*/
public static boolean le(double a, double b) {
return a <= b;
}
}