The com.io7m.jtensors package implements a set of efficient vector, matrix, and
quaternion classes intended for use in computer graphics applications.
The package uses simple and efficient algorithms for all operations. The design of
the package distinguishes
between computation and storage tensors. This allows code that
computes with vectors to consist entirely of static,
monomorphic
method calls - the type of code that produces the best results under Java virtual
machines that use JIT
compilation.
The package also provides storage tensors that are backed by direct memory, allowing
for zero-copy sharing of structures with native code.
The package includes a large battery of automated tests that attempt to verify the
correctness of the included
implementations. As of the time of writing, the tests manage 100% coverage for all
code.
The project can be compiled and installed with
Maven:
All
io7m.com packages use Semantic Versioning
, which implies that it is always safe to use
version ranges with an exclusive upper bound equal to the next major version - the
API of the package will not
change in a backwards-incompatible manner before the next major version.
There are no known platform-specific issues.
All files distributed with the com.io7m.jtensors package are placed under the
following license:
The com.io7m.jtensors package provides
computation
vectors with single-precision
(float)
elements, double-precision
(double)
elements, integer
(int), and long integer
(long)
elements. Each vector type is available in two, three, and four element versions.
The package unambiguously
identifies the vector types by using the following naming conventions for the types
(given as a simple EBNF
grammar) :
Computation vectors are always immutable and are defined in such a way to allow the
Java virtual machine to
efficiently inline all vector method calls and to eliminate the allocations of intermediate
vectors via
escape analysis.
The available vector types include:
The
com.io7m.jtensors package provides mutable
storage
vectors. A
storage vector is a mutable vector upon which only very simple
get
and
set operations are defined. The intention is to allow all intermediate computations
to be written with immutable
computation
vectors, with the final results of those computations being written to storage vectors
in order to, for example,
be passed directly to native code without requiring copying.
To enumerate the available storage vector types, see the API documentation for the
VectorStorageType
interface.
The com.io7m.jtensors package also provides copies of the existing
vector types indexed by a phantom type parameter in order to allow the programmer
to make semantically distinct
values type-incompatible.
The com.io7m.jtensors package provides square
computation
matrices with single-precision
(float)
elements, and double-precision
(double)
elements. Each matrix type is available in 2x2, 3x3, and 4x4 versions. The package
unambiguously identifies the
matrix types by using the following naming conventions for the types (given as a simple
EBNF grammar):
Computation matrices are always immutable and are defined in such a way to allow the
Java virtual machine to
efficiently inline all matrix method calls and to eliminate the allocations of intermediate
matrices
via escape analysis.
The available matrix types include:
The
com.io7m.jtensors package provides mutable
storage
matrices. A
storage matrix is a mutable matrix upon which only very simple
get
and
set operations are defined. The intention is to allow all intermediate computations
to be written with immutable
computation
matrices, with the final results of those computations being written to storage matrices
in order to, for example,
be passed directly to native code without requiring copying.
To enumerate the available storage matrix types, see the API documentation for the
MatrixStorageType
interface.
Matrix data is stored in column-major format
, in whatever is the platform's native byte order.
For an m x m square matrix, assuming that each element of the matrix uses
n
bytes, the first byte of the element at row
r
and column
c
(assuming 0 <= r < m and
0 <= c < m) can be found by
(c * m * n) + (r * n).
So, the element at row 0, column 0 would be stored in
bytes [0 .. 3]. The element at row
1, column 0 would be stored in bytes [4 .. 7].
The element at row 0, column 1 would be stored in bytes
[16 .. 19], and so on.
As with the vector types, the com.io7m.jtensors package provides copies of all
the existing matrix types indexed by a pair of phantom type parameters.
Conceptually, a matrix can be considered as storing a transform from coordinate space
T0
to space T1. For a 4x4 matrix in the
com.io7m.jtensors
package, this is denoted by the type
PMatrix4x4D<T0,T1>. It then follows that when matrices are concatenated via
multiplications, their type parameters are translated accordingly. For example, a
matrix
PMatrix4x4D<T0,T1>
multiplied by a matrix
PMatrix4x4D<T1,T2>
results in a matrix of type
PMatrix4x4D<T0,T2>. Inverting a matrix results in a matrix that represents
the inverse of the original transform that the matrix represented. For example, inverting
a matrix of type
PMatrix4x4D<T0,T1>
results in a matrix of type PMatrix4x4D<T1,T0>.
Type parameters are also translated across multiplications by vectors. A multiplication
of a vector of type
PVector4D<T0>
by a matrix of type
PMatrix4x4D<T0,T1>
results in a vector of type
PVector4D<T1>.
Being able to track the types of transforms at this level of detail is invaluable
when using systems such as
OpenGL, where accidentally mixing up matrices tends to result in visual anomalies
that can be extremely hard to
track down. By explicitly denoting coordinate spaces with empty types, it's possible
to statically prevent all
bugs involving accidentally mixing up matrices. It's also possible to prevent the
incorrect construction of
matrices . Additionally, with each matrix labelled by
the type of transform it represents, code becomes self-documenting.
The com.io7m.jtensors package provides quaternions with single-precision
(float)
elements, and double-precision
(double)
elements. The package unambiguously identifies the quaternion types by using the following
naming conventions for
the types (given as a simple EBNF grammar) :
The available quaternion types include:
API documentation for the package is provided via the included
Javadoc.