lwjgl2-arm64/src/java/org/lwjgl/Math.java

1256 lines
38 KiB
Java
Raw Normal View History

2002-08-15 17:46:18 +02:00
/*
* Copyright (c) 2002 Light Weight Java Game Library Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
2002-08-09 12:56:30 +02:00
*
2002-08-15 17:46:18 +02:00
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'Light Weight Java Game Library' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2002-08-09 12:56:30 +02:00
*/
2002-08-15 17:46:18 +02:00
2002-08-09 12:56:30 +02:00
package org.lwjgl;
/**
2002-08-15 17:46:18 +02:00
* $Id$
*
2002-08-09 12:56:30 +02:00
* A floating point math library, with vector processing capabilities.
* This class differs significantly from its java.lang.Math counterpart
* in that it a) makes no claims about strict accuracy and b) uses degrees
* rather than radians for its functions which are more friendly to use.
*
2002-08-15 17:46:18 +02:00
* @author cix_foo <cix_foo@users.sourceforge.net>
* @version $Revision$
2002-08-09 12:56:30 +02:00
*/
public final class Math {
static {
System.loadLibrary(Sys.LIBRARY_NAME);
}
2002-08-19 13:29:42 +02:00
2002-08-09 12:56:30 +02:00
/** Floating point version of pi */
2002-08-19 13:29:42 +02:00
public static final float PI = (float) java.lang.Math.PI;
2002-08-09 12:56:30 +02:00
/*
* Unary matrix operations
*/
2002-08-19 13:29:42 +02:00
private static abstract class UnaryMatrixOperation {
private final int enum;
private final String name;
UnaryMatrixOperation(int enum, String name) {
this.enum = enum;
this.name = name;
}
public String toString() {
return name;
}
abstract MatrixOpClassification classify();
}
/**
* A matrix operation is unsafe if the source and destination overlap,
* and either the strides are not equal, or destination > source, which
* would give an undefined result
*/
private static final MatrixOpClassification MATRIXOP_UNSAFE = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return this; }
protected MatrixOpClassification safe() { return this; }
protected MatrixOpClassification direct() { return this; }
protected MatrixOpClassification offset() { return this; }
void execute(
int leftSourceAddress,
int leftSourceStride,
int leftElements,
int leftSourceWidth,
int leftSourceHeight,
boolean transposeLeftSource,
int rightSourceAddress,
int rightSourceStride,
int rightElements,
int rightSourceWidth,
int rightSourceHeight,
boolean transposeRightSource,
int destAddress,
int destStride,
boolean transposeDest)
{
throw new IllegalArgumentException("Unsafe matrix operation.");
}
void execute(
int sourceAddress,
int sourceStride,
int numElements,
int sourceWidth,
int sourceHeight,
boolean transposeSource,
int destAddress,
int destStride,
boolean transposeDest)
{
throw new IllegalArgumentException("Unsafe matrix operation.");
}
};
/** Straight copy */
public static final class MatrixOpCopy extends UnaryMatrixOperation {
MatrixOpCopy() {
super(0, "copy");
}
MatrixOpClassification classify() {
return MATRIXOP_NONE;
}
/**
* Unclassified (initial state) matrix operation.
*/
private final MatrixOpClassification MATRIXOP_NONE = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return MATRIXOP_SAFE; }
protected MatrixOpClassification direct() { return MATRIXOP_DIRECT; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
};
/**
* A matrix operation is direct if the source and destination addresses
* are the same, and the strides are the same.
*/
private final MatrixOpClassification MATRIXOP_DIRECT = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return this; }
protected MatrixOpClassification direct() { return this; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
void execute(
int sourceAddress,
int sourceStride,
int numElements,
int sourceWidth,
int sourceHeight,
boolean transposeSource,
int destAddress,
int destStride,
boolean transposeDest)
{
}
};
/**
* A matrix operation is offset if source > destination, and the
* strides are the same
*/
private final MatrixOpClassification MATRIXOP_OFFSET = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return this; }
protected MatrixOpClassification direct() { return this; }
protected MatrixOpClassification offset() { return this; }
void execute(
int sourceAddress,
int sourceStride,
int numElements,
int sourceWidth,
int sourceHeight,
boolean transposeSource,
int destAddress,
int destStride,
boolean transposeDest)
{
}
};
2002-08-09 12:56:30 +02:00
2002-08-19 13:29:42 +02:00
/**
* A matrix operation is safe if the source and destination do not
* overlap in any way
*/
private final MatrixOpClassification MATRIXOP_SAFE = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return MATRIXOP_SAFE; }
protected MatrixOpClassification direct() { return MATRIXOP_DIRECT; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
void execute(
int sourceAddress,
int sourceStride,
int numElements,
int sourceWidth,
int sourceHeight,
boolean transposeSource,
int destAddress,
int destStride,
boolean transposeDest)
{
}
};
};
public static final MatrixOpCopy MATRIXOP_COPY = new MatrixOpCopy();
2002-08-09 12:56:30 +02:00
/** Negate the vector */
2002-08-19 13:29:42 +02:00
public static final class MatrixOpNegate extends UnaryMatrixOperation {
MatrixOpNegate() {
super(1, "negate");
}
MatrixOpClassification classify() {
return MATRIXOP_NONE;
}
/**
* Unclassified (initial state) matrix operation.
*/
private final MatrixOpClassification MATRIXOP_NONE = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return MATRIXOP_SAFE; }
protected MatrixOpClassification direct() { return MATRIXOP_DIRECT; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
};
/**
* A matrix operation is direct if the source and destination addresses
* are the same, and the strides are the same.
*/
private final MatrixOpClassification MATRIXOP_DIRECT = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return this; }
protected MatrixOpClassification direct() { return this; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
void execute(
int sourceAddress,
int sourceStride,
int numElements,
int sourceWidth,
int sourceHeight,
boolean transposeSource,
int destAddress,
int destStride,
boolean transposeDest)
{
}
};
2002-08-09 12:56:30 +02:00
2002-08-19 13:29:42 +02:00
/**
* A matrix operation is offset if source > destination, and the
* strides are the same
*/
private final MatrixOpClassification MATRIXOP_OFFSET = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return this; }
protected MatrixOpClassification direct() { return this; }
protected MatrixOpClassification offset() { return this; }
void execute(
int sourceAddress,
int sourceStride,
int numElements,
int sourceWidth,
int sourceHeight,
boolean transposeSource,
int destAddress,
int destStride,
boolean transposeDest)
{
}
};
/**
* A matrix operation is safe if the source and destination do not
* overlap in any way
*/
private final MatrixOpClassification MATRIXOP_SAFE = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return MATRIXOP_SAFE; }
protected MatrixOpClassification direct() { return MATRIXOP_DIRECT; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
void execute(
int sourceAddress,
int sourceStride,
int numElements,
int sourceWidth,
int sourceHeight,
boolean transposeSource,
int destAddress,
int destStride,
boolean transposeDest)
{
}
};
};
public static final MatrixOpNegate MATRIXOP_NEGATE = new MatrixOpNegate();
2002-08-09 12:56:30 +02:00
/** Normalise the vector (set to length 1) */
2002-08-19 13:29:42 +02:00
public static final class MatrixOpNormalise extends UnaryMatrixOperation {
MatrixOpNormalise() {
super(2, "normalise");
}
MatrixOpClassification classify() {
return MATRIXOP_NONE;
}
/**
* Unclassified (initial state) matrix operation.
*/
private final MatrixOpClassification MATRIXOP_NONE = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return MATRIXOP_SAFE; }
protected MatrixOpClassification direct() { return MATRIXOP_DIRECT; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
};
/**
* A matrix operation is direct if the source and destination addresses
* are the same, and the strides are the same.
*/
private final MatrixOpClassification MATRIXOP_DIRECT = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return this; }
protected MatrixOpClassification direct() { return this; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
void execute(
int sourceAddress,
int sourceStride,
int numElements,
int sourceWidth,
int sourceHeight,
boolean transposeSource,
int destAddress,
int destStride,
boolean transposeDest)
{
}
};
2002-08-09 12:56:30 +02:00
2002-08-19 13:29:42 +02:00
/**
* A matrix operation is offset if source > destination, and the
* strides are the same
*/
private final MatrixOpClassification MATRIXOP_OFFSET = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return this; }
protected MatrixOpClassification direct() { return this; }
protected MatrixOpClassification offset() { return this; }
void execute(
int sourceAddress,
int sourceStride,
int numElements,
int sourceWidth,
int sourceHeight,
boolean transposeSource,
int destAddress,
int destStride,
boolean transposeDest)
{
}
};
/**
* A matrix operation is safe if the source and destination do not
* overlap in any way
*/
private final MatrixOpClassification MATRIXOP_SAFE = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return MATRIXOP_SAFE; }
protected MatrixOpClassification direct() { return MATRIXOP_DIRECT; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
void execute(
int sourceAddress,
int sourceStride,
int numElements,
int sourceWidth,
int sourceHeight,
boolean transposeSource,
int destAddress,
int destStride,
boolean transposeDest)
{
}
};
};
public static final MatrixOpNormalise MATRIXOP_NORMALISE = new MatrixOpNormalise();
2002-08-09 12:56:30 +02:00
/** Compute the inverse matrix */
2002-08-19 13:29:42 +02:00
public static final class MatrixOpInvert extends UnaryMatrixOperation {
MatrixOpInvert() {
super(3, "invert");
}
MatrixOpClassification classify() {
return MATRIXOP_NONE;
}
/**
* Unclassified (initial state) matrix operation.
*/
private final MatrixOpClassification MATRIXOP_NONE = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return MATRIXOP_SAFE; }
protected MatrixOpClassification direct() { return MATRIXOP_DIRECT; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
};
/**
* A matrix operation is direct if the source and destination addresses
* are the same, and the strides are the same.
*/
private final MatrixOpClassification MATRIXOP_DIRECT = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return this; }
protected MatrixOpClassification direct() { return this; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
void execute(
int sourceAddress,
int sourceStride,
int numElements,
int sourceWidth,
int sourceHeight,
boolean transposeSource,
int destAddress,
int destStride,
boolean transposeDest)
{
}
};
2002-08-09 12:56:30 +02:00
2002-08-19 13:29:42 +02:00
/**
* A matrix operation is offset if source > destination, and the
* strides are the same
*/
private final MatrixOpClassification MATRIXOP_OFFSET = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return this; }
protected MatrixOpClassification direct() { return this; }
protected MatrixOpClassification offset() { return this; }
void execute(
int sourceAddress,
int sourceStride,
int numElements,
int sourceWidth,
int sourceHeight,
boolean transposeSource,
int destAddress,
int destStride,
boolean transposeDest)
{
}
};
/**
* A matrix operation is safe if the source and destination do not
* overlap in any way
*/
private final MatrixOpClassification MATRIXOP_SAFE = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return MATRIXOP_SAFE; }
protected MatrixOpClassification direct() { return MATRIXOP_DIRECT; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
void execute(
int sourceAddress,
int sourceStride,
int numElements,
int sourceWidth,
int sourceHeight,
boolean transposeSource,
int destAddress,
int destStride,
boolean transposeDest)
{
}
};
};
public static final MatrixOpInvert MATRIXOP_INVERT = new MatrixOpInvert();
2002-08-09 12:56:30 +02:00
/*
* Binary matrix operations
*/
2002-08-19 13:29:42 +02:00
private static abstract class BinaryMatrixOperation {
private final int enum;
private final String name;
BinaryMatrixOperation(int enum, String name) {
this.enum = enum;
this.name = name;
}
public String toString() {
return name;
}
/**
* Check the compatibility of a binary matrix operation.
* @throws IllegalArgumentException if the source and destinations are not
* compatible
*/
abstract void checkCompatibility(
int leftSourceWidth,
int leftSourceHeight,
boolean transposeLeftSource,
int rightSourceWidth,
int rightSourceHeight,
boolean transposeRightSource,
boolean transposeDest);
abstract MatrixOpClassification classify();
}
2002-08-09 12:56:30 +02:00
/** Multiply left source by right source */
2002-08-19 13:29:42 +02:00
public static final class MatrixOpMultiply extends BinaryMatrixOperation {
MatrixOpMultiply() {
super(0, "multiply");
}
void checkCompatibility(
int leftSourceWidth,
int leftSourceHeight,
boolean transposeLeftSource,
int rightSourceWidth,
int rightSourceHeight,
boolean transposeRightSource,
boolean transposeDest)
{
// Left matrix width must be the same as right matrix height.
int leftWidth = transposeLeftSource ? leftSourceHeight : leftSourceWidth;
int rightHeight = transposeRightSource ? rightSourceWidth : rightSourceHeight;
if (leftWidth != rightHeight)
throw new IllegalArgumentException("Left and right matrices are not compatible.");
}
MatrixOpClassification classify() {
return MATRIXOP_NONE;
}
/**
* Unclassified (initial state) matrix operation.
*/
private final MatrixOpClassification MATRIXOP_NONE = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return MATRIXOP_SAFE; }
protected MatrixOpClassification direct() { return MATRIXOP_DIRECT; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
};
/**
* A matrix operation is direct if the source and destination addresses
* are the same, and the strides are the same.
*/
private final MatrixOpClassification MATRIXOP_DIRECT = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return this; }
protected MatrixOpClassification direct() { return this; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
void execute(
int leftSourceAddress,
int leftSourceStride,
int leftElements,
int leftSourceWidth,
int leftSourceHeight,
boolean transposeLeftSource,
int rightSourceAddress,
int rightSourceStride,
int rightElements,
int rightSourceWidth,
int rightSourceHeight,
boolean transposeRightSource,
int destAddress,
int destStride,
boolean transposeDest)
{
}
};
/**
* A matrix operation is offset if source > destination, and the
* strides are the same
*/
private final MatrixOpClassification MATRIXOP_OFFSET = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return this; }
protected MatrixOpClassification direct() { return this; }
protected MatrixOpClassification offset() { return this; }
void execute(
int leftSourceAddress,
int leftSourceStride,
int leftElements,
int leftSourceWidth,
int leftSourceHeight,
boolean transposeLeftSource,
int rightSourceAddress,
int rightSourceStride,
int rightElements,
int rightSourceWidth,
int rightSourceHeight,
boolean transposeRightSource,
int destAddress,
int destStride,
boolean transposeDest)
{
}
};
2002-08-09 12:56:30 +02:00
2002-08-19 13:29:42 +02:00
/**
* A matrix operation is safe if the source and destination do not
* overlap in any way
*/
private final MatrixOpClassification MATRIXOP_SAFE = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return MATRIXOP_SAFE; }
protected MatrixOpClassification direct() { return MATRIXOP_DIRECT; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
void execute(
int leftSourceAddress,
int leftSourceStride,
int leftElements,
int leftSourceWidth,
int leftSourceHeight,
boolean transposeLeftSource,
int rightSourceAddress,
int rightSourceStride,
int rightElements,
int rightSourceWidth,
int rightSourceHeight,
boolean transposeRightSource,
int destAddress,
int destStride,
boolean transposeDest)
{
}
};
};
public static final MatrixOpMultiply MATRIXOP_MULTIPLY = new MatrixOpMultiply();
2002-08-09 12:56:30 +02:00
/** Add right source to left source */
2002-08-19 13:29:42 +02:00
public static final class MatrixOpAdd extends BinaryMatrixOperation {
MatrixOpAdd() {
super(1, "add");
}
void checkCompatibility(
int leftSourceWidth,
int leftSourceHeight,
boolean transposeLeftSource,
int rightSourceWidth,
int rightSourceHeight,
boolean transposeRightSource,
boolean transposeDest)
{
if (transposeLeftSource == transposeRightSource) {
// Left and right must be the same size
if (leftSourceWidth != rightSourceWidth || leftSourceHeight != rightSourceHeight)
throw new IllegalArgumentException("Left and right matrices are not the same size.");
} else {
// Left and right must be the same size but one of them is transposed
if (leftSourceWidth != rightSourceHeight || leftSourceHeight != rightSourceWidth)
throw new IllegalArgumentException("Left and right matrices are not the same size.");
}
}
MatrixOpClassification classify() {
return MATRIXOP_NONE;
}
/**
* Unclassified (initial state) matrix operation.
*/
private final MatrixOpClassification MATRIXOP_NONE = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return MATRIXOP_SAFE; }
protected MatrixOpClassification direct() { return MATRIXOP_DIRECT; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
};
/**
* A matrix operation is direct if the source and destination addresses
* are the same, and the strides are the same.
*/
private final MatrixOpClassification MATRIXOP_DIRECT = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return this; }
protected MatrixOpClassification direct() { return this; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
void execute(
int leftSourceAddress,
int leftSourceStride,
int leftElements,
int leftSourceWidth,
int leftSourceHeight,
boolean transposeLeftSource,
int rightSourceAddress,
int rightSourceStride,
int rightElements,
int rightSourceWidth,
int rightSourceHeight,
boolean transposeRightSource,
int destAddress,
int destStride,
boolean transposeDest)
{
}
};
2002-08-09 12:56:30 +02:00
2002-08-19 13:29:42 +02:00
/**
* A matrix operation is offset if source > destination, and the
* strides are the same
*/
private final MatrixOpClassification MATRIXOP_OFFSET = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return this; }
protected MatrixOpClassification direct() { return this; }
protected MatrixOpClassification offset() { return this; }
void execute(
int leftSourceAddress,
int leftSourceStride,
int leftElements,
int leftSourceWidth,
int leftSourceHeight,
boolean transposeLeftSource,
int rightSourceAddress,
int rightSourceStride,
int rightElements,
int rightSourceWidth,
int rightSourceHeight,
boolean transposeRightSource,
int destAddress,
int destStride,
boolean transposeDest)
{
}
};
/**
* A matrix operation is safe if the source and destination do not
* overlap in any way
*/
private final MatrixOpClassification MATRIXOP_SAFE = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return MATRIXOP_SAFE; }
protected MatrixOpClassification direct() { return MATRIXOP_DIRECT; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
void execute(
int leftSourceAddress,
int leftSourceStride,
int leftElements,
int leftSourceWidth,
int leftSourceHeight,
boolean transposeLeftSource,
int rightSourceAddress,
int rightSourceStride,
int rightElements,
int rightSourceWidth,
int rightSourceHeight,
boolean transposeRightSource,
int destAddress,
int destStride,
boolean transposeDest)
{
}
};
};
public static final MatrixOpAdd MATRIXOP_ADD = new MatrixOpAdd();
2002-08-09 12:56:30 +02:00
/** Subtract right source from left source */
2002-08-19 13:29:42 +02:00
public static final class MatrixOpSubtract extends BinaryMatrixOperation {
MatrixOpSubtract() {
super(2, "subtract");
}
void checkCompatibility(
int leftSourceWidth,
int leftSourceHeight,
boolean transposeLeftSource,
int rightSourceWidth,
int rightSourceHeight,
boolean transposeRightSource,
boolean transposeDest)
{
// Same as for add, obviously...
MATRIXOP_ADD.checkCompatibility(
leftSourceWidth,
leftSourceHeight,
transposeLeftSource,
rightSourceWidth,
rightSourceHeight,
transposeRightSource,
transposeDest
);
}
MatrixOpClassification classify() {
return MATRIXOP_NONE;
}
/**
* Unclassified (initial state) matrix operation.
*/
private final MatrixOpClassification MATRIXOP_NONE = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return MATRIXOP_SAFE; }
protected MatrixOpClassification direct() { return MATRIXOP_DIRECT; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
};
/**
* A matrix operation is direct if the source and destination addresses
* are the same, and the strides are the same.
*/
private final MatrixOpClassification MATRIXOP_DIRECT = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return this; }
protected MatrixOpClassification direct() { return this; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
native void execute(
int leftSourceAddress,
int leftSourceStride,
int leftElements,
int leftSourceWidth,
int leftSourceHeight,
boolean transposeLeftSource,
int rightSourceAddress,
int rightSourceStride,
int rightElements,
int rightSourceWidth,
int rightSourceHeight,
boolean transposeRightSource,
int destAddress,
int destStride,
boolean transposeDest);
};
/**
* A matrix operation is offset if source > destination, and the
* strides are the same
*/
private final MatrixOpClassification MATRIXOP_OFFSET = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return this; }
protected MatrixOpClassification direct() { return this; }
protected MatrixOpClassification offset() { return this; }
native void execute(
int leftSourceAddress,
int leftSourceStride,
int leftElements,
int leftSourceWidth,
int leftSourceHeight,
boolean transposeLeftSource,
int rightSourceAddress,
int rightSourceStride,
int rightElements,
int rightSourceWidth,
int rightSourceHeight,
boolean transposeRightSource,
int destAddress,
int destStride,
boolean transposeDest);
};
/**
* A matrix operation is safe if the source and destination do not
* overlap in any way
*/
private final MatrixOpClassification MATRIXOP_SAFE = new MatrixOpClassification() {
protected MatrixOpClassification unsafe() { return MATRIXOP_UNSAFE; }
protected MatrixOpClassification safe() { return MATRIXOP_SAFE; }
protected MatrixOpClassification direct() { return MATRIXOP_DIRECT; }
protected MatrixOpClassification offset() { return MATRIXOP_OFFSET; }
native void execute(
int leftSourceAddress,
int leftSourceStride,
int leftElements,
int leftSourceWidth,
int leftSourceHeight,
boolean transposeLeftSource,
int rightSourceAddress,
int rightSourceStride,
int rightElements,
int rightSourceWidth,
int rightSourceHeight,
boolean transposeRightSource,
int destAddress,
int destStride,
boolean transposeDest);
};
};
public static final MatrixOpSubtract MATRIXOP_SUBTRACT = new MatrixOpSubtract();
2002-08-09 12:56:30 +02:00
/**
* No constructor for Math.
*/
private Math() {
super();
}
2002-08-19 13:29:42 +02:00
2002-08-09 12:56:30 +02:00
/**
* Return the sine of theta
*
* @param theta angle in degrees
* @return sin(theta)
*/
2002-08-19 13:29:42 +02:00
public static float sin(float theta) {
return (float) java.lang.Math.sin(java.lang.Math.toRadians(theta));
}
2002-08-09 12:56:30 +02:00
/**
* Return the cosine of theta
*
* @param theta angle in degrees
* @return cos(theta)
*/
2002-08-19 13:29:42 +02:00
public static float cos(float theta) {
return (float) java.lang.Math.cos(java.lang.Math.toRadians(theta));
}
2002-08-09 12:56:30 +02:00
/**
* Return the tangent of theta
*
* @param theta angle in degrees
* @return tan(theta)
*/
2002-08-19 13:29:42 +02:00
public static float tan(float theta) {
return (float) java.lang.Math.tan(java.lang.Math.toRadians(theta));
}
2002-08-09 12:56:30 +02:00
/**
* Return the inverse sine of theta
*
* @param theta angle in degrees
* @return asin(theta)
*/
2002-08-19 13:29:42 +02:00
public static float asin(float theta) {
return (float) java.lang.Math.toDegrees(java.lang.Math.asin(theta));
}
2002-08-09 12:56:30 +02:00
/**
* Return the inverse cosine of theta
*
* @param theta angle in degrees
* @return acos(theta)
*/
2002-08-19 13:29:42 +02:00
public static float acos(float theta) {
return (float) java.lang.Math.toDegrees(java.lang.Math.acos(theta));
}
2002-08-09 12:56:30 +02:00
/**
* Return the inverse tangent of theta
*
* @param theta angle in degrees
* @return atan(theta)
*/
2002-08-19 13:29:42 +02:00
public static float atan(float theta) {
return (float) java.lang.Math.toDegrees(java.lang.Math.atan(theta));
}
2002-08-09 12:56:30 +02:00
/**
* Return the square root of a value
* @param n the number for which you want the square root
* @return sqrt(n)
*/
2002-08-19 13:29:42 +02:00
public static float sqrt(float n) {
return (float) java.lang.Math.sqrt(n);
}
/*
* Matrix operation classifications
*/
private static abstract class MatrixOpClassification {
abstract MatrixOpClassification unsafe();
abstract MatrixOpClassification safe();
abstract MatrixOpClassification direct();
abstract MatrixOpClassification offset();
/**
* Execute a unary matrix operation.
* The default implementation does nothing.
*/
void execute(
int sourceAddress,
int sourceStride,
int numElements,
int sourceWidth,
int sourceHeight,
boolean transposeSource,
int destAddress,
int destStride,
boolean transposeDest) {
}
/**
* Execute a binary matrix operation.
* The default implementation does nothing.
*/
void execute(
int leftSourceAddress,
int leftSourceStride,
int leftElements,
int leftSourceWidth,
int leftSourceHeight,
boolean transposeLeftSource,
int rightSourceAddress,
int rightSourceStride,
int rightElements,
int rightSourceWidth,
int rightSourceHeight,
boolean transposeRightSource,
int destAddress,
int destStride,
boolean transposeDest) {
}
public final MatrixOpClassification check(
int sourceAddress,
int sourceStride,
int numElements,
int destAddress,
int destStride)
{
int sourceEnd = sourceAddress + sourceStride * numElements;
int destEnd = destAddress + destStride * numElements;
// Check to see if source is somewhere inside the destination
if ((sourceAddress >= destAddress && sourceAddress <= destEnd)
|| (sourceEnd >= destAddress && sourceEnd <= destEnd)) {
// Check out the strides first
if (destAddress > sourceAddress || sourceStride != destStride)
return unsafe();
else if (destAddress < sourceAddress)
return offset();
else
return direct();
} else {
// Completely safe
return safe();
}
}
}
2002-08-09 12:56:30 +02:00
/**
* Apply a unary matrix operation to an array of matrices.
* @param operation A unary vector operation which must be one of
* MATRIXOP_NOOP,
* MATRIXOP_NEGATE,
* MATRIXOP_NORMALIZE, etc.
* @param sourceAddress The address of the source matrices
* @param sourceStride The distance between source matrices, in bytes; if 0,
* it is assumed that the matrices are tightly packed. This is equivalent to
* sourceStride == sourceWidth * sourceHeight * 4
* @param numElements The number of matrices
* @param sourceWidth The width of the source matrix. Must be > 0.
* @param sourceHeight The height of the source matrix. Must be > 0.
* @param transposeSource The source can be transposed automatically before
* the operation is performed on it
* @param destAddress The results are placed here. This may overlap the
* source and can even be the same, which performs the unary operation
* in-situ
* @param destStride The distance between destination matrices, in bytes,
* similar to sourceStride. Note that if the source and destination address
* overlap and the strides are different then the result is undefined.
* @param transposeDest The destination can be transposed before being
* written
*/
2002-08-19 13:29:42 +02:00
public static void matrixOp(
UnaryMatrixOperation operation,
2002-08-09 12:56:30 +02:00
int sourceAddress,
int sourceStride,
int numElements,
int sourceWidth,
int sourceHeight,
boolean transposeSource,
int destAddress,
int destStride,
2002-08-19 13:29:42 +02:00
boolean transposeDest) {
// Check that certain parameters are legal in the first place
assert sourceAddress != 0 : "0 source address";
assert sourceStride >= 0 : "Illegal source stride";
assert numElements >= 0 : "Illegal number of elements";
assert sourceWidth >= 1 : "Illegal source width";
assert sourceHeight >= 1 : "Illegal source height";
assert destAddress != 0 : "0 dest address";
assert destStride >= 0 : "Illegal dest stride";
// Calculate actual strides
if (sourceStride == 0)
sourceStride = sourceWidth * sourceHeight;
if (destStride == 0)
destStride = sourceStride;
// Check unary matrix operation type
MatrixOpClassification op = operation.classify().check(sourceAddress, sourceStride, numElements, destAddress, destStride);
op.execute(
sourceAddress,
sourceStride,
numElements,
sourceWidth,
sourceHeight,
transposeSource,
destAddress,
destStride,
transposeDest
);
}
2002-08-09 12:56:30 +02:00
/**
* Apply a binary matrix operation to two arrays of matrices. The results
* are computed by applying the first right element to each of the left
* elements in turn; then the second right element to each left element;
* and so on.
* @param operation A binary vector operation which must be one of
* MATRIXOP_MUTLIPLY,
* MATRIXOP_ADD,
* MATRIXOP_SUBTRACT, etc.
* @param leftSourceAddress The address of the source matrices
* @param leftSourceStride The distance between source matrices, in bytes; if 0,
* it is assumed that the matrices are tightly packed. This is equivalent to
* sourceStride == sourceWidth * sourceHeight * 4
* @param leftElements The number of left-hand-side matrices
* @param leftSourceWidth The width of the left source matrix. Must be > 0.
* @param leftSourceHeight The height of the left source matrix. Must be > 0.
* @param transposeLeftSource The left source can be transposed automatically before
* the operation is performed on it
* @param rightSourceAddress The address of the right source matrices
* @param rightSourceStride The distance between right source matrices, in bytes; if 0,
* it is assumed that the matrices are tightly packed. This is equivalent to
* sourceStride == sourceWidth * sourceHeight * 4
* @param rightElements The number of right-hand-side matrices
* @param rightSourceWidth The width of the right source matrix. Must be > 0.
* @param rightSourceHeight The height of the right source matrix. Must be > 0.
* @param transposeRightSource The right source can be transposed automatically before
* the operation is performed on it
* @param destAddress The results are placed here. This may overlap the
* sources and can even be the same, which performs the binary operation
* in-situ
* @param destStride The distance between destination matrices, in bytes,
* similar to sourceStride. Note that if the source and destination address
* overlap and the strides are different then the result is undefined.
* @param transposeDest The destination can be transposed before being
* written
2002-08-19 13:29:42 +02:00
* @throws IllegalArgumentException if the source matrices are incompatible
2002-08-09 12:56:30 +02:00
*/
2002-08-19 13:29:42 +02:00
public static void matrixOp(
BinaryMatrixOperation operation,
2002-08-09 12:56:30 +02:00
int leftSourceAddress,
int leftSourceStride,
2002-08-19 13:29:42 +02:00
int leftElements,
2002-08-09 12:56:30 +02:00
int leftSourceWidth,
int leftSourceHeight,
boolean transposeLeftSource,
int rightSourceAddress,
int rightSourceStride,
2002-08-19 13:29:42 +02:00
int rightElements,
2002-08-09 12:56:30 +02:00
int rightSourceWidth,
int rightSourceHeight,
boolean transposeRightSource,
int destAddress,
int destStride,
2002-08-19 13:29:42 +02:00
boolean transposeDest) {
// Check that certain parameters are legal in the first place
assert leftSourceAddress != 0 : "0 left source address";
assert leftSourceStride >= 0 : "Illegal left source stride";
assert leftElements >= 0 : "Illegal number of left elements";
assert leftSourceWidth >= 1 : "Illegal left source width";
assert leftSourceHeight >= 1 : "Illegal left source height";
assert rightSourceAddress != 0 : "0 right source address";
assert rightSourceStride >= 0 : "Illegal right source stride";
assert rightElements >= 0 : "Illegal number of right elements";
assert rightSourceWidth >= 1 : "Illegal right source width";
assert rightSourceHeight >= 1 : "Illegal right source height";
assert destAddress != 0 : "0 dest address";
assert destStride >= 0 : "Illegal dest stride";
// Calculate actual strides
if (leftSourceStride == 0)
leftSourceStride = leftSourceWidth * leftSourceHeight;
if (rightSourceStride == 0)
rightSourceStride = rightSourceWidth * rightSourceHeight;
// Ensure the source and destination matrices are compatible
operation.checkCompatibility(
leftSourceWidth,
leftSourceHeight,
transposeLeftSource,
rightSourceWidth,
rightSourceWidth,
transposeRightSource,
transposeDest);
if (destStride == 0) {
// Calculate the destination stride from the input matrix sizes
}
// Check unary matrix operation type
MatrixOpClassification op = operation.classify().check(leftSourceAddress, leftSourceStride, leftElements, destAddress, destStride);
op = op.check(rightSourceAddress, rightSourceStride, rightElements, destAddress, destStride);
op.execute(
leftSourceAddress,
leftSourceStride,
leftElements,
leftSourceWidth,
leftSourceHeight,
transposeLeftSource,
rightSourceAddress,
rightSourceStride,
rightElements,
rightSourceWidth,
rightSourceHeight,
transposeRightSource,
destAddress,
destStride,
transposeDest
);
}
2002-08-09 12:56:30 +02:00
}