2114 lines
86 KiB
Plaintext
2114 lines
86 KiB
Plaintext
/**
|
||
<div style="width:800px;text-align:justify;">
|
||
|
||
@page ax AX
|
||
|
||
@section axlanguage AX Language Documentation
|
||
@par
|
||
Welcome to the AX Language documentation. These docs provide detailed
|
||
information on the AX language including syntax, data types, available
|
||
functionality (including OpenVDB specific methods) execution structure and
|
||
control flow. See the @subpage axcplusplus documentation for the C++ developer
|
||
documentation.
|
||
@note
|
||
Some sections of this document are still to be completed. Please get in touch
|
||
should you have any questions!
|
||
|
||
@section axcontents Contents
|
||
- @ref axintro
|
||
- @ref axprograms
|
||
- @ref axprogramexample
|
||
- @ref axexecutionxcontext
|
||
- @ref axdatatypes
|
||
- @ref axscalars
|
||
- @ref axvecmats
|
||
- @ref axstrings
|
||
- @ref axtypeprecedence
|
||
- @ref axoperators
|
||
- @ref axopbinary
|
||
- @ref axopassignment
|
||
- @ref axopbinarithmetic
|
||
- @ref axopcomparison
|
||
- @ref axopbinlogical
|
||
- @ref axopunary
|
||
- @ref axopunarithmetic
|
||
- @ref axopunlogical
|
||
- @ref axopunincdec
|
||
- @ref axopaccess
|
||
- @ref axopother
|
||
- @ref axopprecedence
|
||
- @ref axtokens
|
||
- @ref axvaridentifiers
|
||
- @ref axliterals
|
||
- @ref axcomments
|
||
- @ref axkeywords
|
||
- @ref axreserved
|
||
- @ref axsyntax
|
||
- @ref axattribaccess
|
||
- @ref axexternalaccess
|
||
- @ref axdecls
|
||
- @ref axscopes
|
||
- @ref axbranching
|
||
- @ref axloops
|
||
- @ref axfunctions
|
||
- @ref axuserfunctions
|
||
- @ref axvexsupport
|
||
- @ref axexamples
|
||
|
||
|
||
@section axintro Introduction
|
||
@par
|
||
AX is a fast and portable JIT compiled expression language, designed for
|
||
writing volume and point kernels represented as OpenVDB grids. It was originally
|
||
developed by the RNDFX team at <A HREF="https://www.dneg.com">DNEG</A> to
|
||
provide a more consistent way for artists to be able to interface with OpenVDB
|
||
data across a variety of in house and external digital content creation software,
|
||
whilst retaining the performance achievable by custom C++ operators.
|
||
@par
|
||
The language is predominately inspired by <A HREF="https://www.sidefx.com/docs/houdini/vex/index.html">SideFX's VEX</A>
|
||
language which itself takes elements from C, C++ and the Renderman Shading
|
||
Language. The design of AX uses concepts from these languages and refrains
|
||
from deviating from their syntax too significantly. Specifically, it does not
|
||
aim to change what are already well established and heavily used language
|
||
syntaxes within the Visual Effects industry; on the contrary, AX aims to provide
|
||
an interface to which a user with previous or little programming experience can
|
||
easily transition to. However, it does introduce new concepts where the
|
||
creators deemed necessary to provide the best and most representative syntax
|
||
relating to the design for OpenVDB volume and point modification.
|
||
|
||
|
||
@section axprograms AX Programs
|
||
@par
|
||
AX programs represent a set of statements which read and write to geometry,
|
||
with each program designed in such a way that it can be executed in a highly
|
||
parallelized framework to access and update individual geometric components.
|
||
For example, consider a mesh with point, vertex and primitive
|
||
attributes. AX programs are designed to run independently across "elements" of
|
||
input geometry and process "attributes" from a particular element. In this case,
|
||
the element level would correlate to either points, vertexes or primitives, and
|
||
a single element would be a unique instance of one of these. These programs are
|
||
at their most efficient writing to the currently processing element, however do
|
||
provide varying levels of access to the geometry as a whole.
|
||
@par
|
||
Note that native AX only supports the modification of OpenVDB data. Currently,
|
||
that means that native AX programs can be written and built for execution over
|
||
OpenVDB Points or OpenVDB Volumes. For any given AX program, the execution context
|
||
(what it's processing) may change what functionality is available and, more
|
||
importantly, the behaviour of reading/writing from attributes. See the @ref axexecutionxcontext
|
||
for details.
|
||
@par
|
||
Whilst powerful, AX is not a catch all replacement for all types of VDB
|
||
operations. Some of this is related to its infancy i.e. missing native support
|
||
for some useful functions, the foundations of which may be supported by AX but
|
||
have not yet been exposed. However there may be certain paradigms which AX is
|
||
better tailored to support than others. Grid reductions, for example, typically
|
||
require the passing of a state between programs; a design pattern which AX is
|
||
less equipped to handle. AX kernels can be abstractly thought of as a "foreach()"
|
||
function (see @ref axprogramexample) and whilst there are ways to achieve
|
||
reductions, it is an example which would be better suited to a custom C++
|
||
implementation.
|
||
@par
|
||
For details of extending AX for custom geometry, see the @subpage axcplusplus
|
||
developer documentation. Note that custom geometry support requires C++ extension.
|
||
|
||
|
||
@subsection axprogramexample A Program Example
|
||
@par
|
||
Before getting into the technical depths of the language, it's a good idea to
|
||
observe a small but complete AX program which could be compiled and executed.
|
||
To begin with, here is a very simple example of a program that reads and writes
|
||
to a particular attribute:
|
||
@par
|
||
<!-- A -->@code{.c}
|
||
// read a floating point attribute from the value of "myattribute"
|
||
float temp = float@myattribute;
|
||
// if the value is less than 0, clamp it to 0
|
||
if (temp < 0.0f) float@myattribute = 0.0f;
|
||
@endcode
|
||
Note that there is no other required logic here to make this a compatible
|
||
program i.e. feeding this code to the @ref vdbaxbinary "vdb_ax command line binary"
|
||
will compile and execute over provided OpenVDB files.
|
||
@par
|
||
The following explains the above example in relation to OpenVDB data; OpenVDB
|
||
points and OpenVDB volumes. The example demonstrates reading from a value on
|
||
some input, either a point attribute or a voxel value, and storing the
|
||
result in a @ref axdecls "local variable". Importantly, the attribute being
|
||
accessed has the name @b `myattribute` and the type @b `float`. The first statement:
|
||
<!-- A -->@code{.c}
|
||
float temp = float@myattribute;
|
||
@endcode
|
||
Invokes a @b read from this attribute (see @ref axattribaccess), retrieving the
|
||
value from the geometry and storing it in the variable @b `temp` to be used in
|
||
the AX program. The second statement:
|
||
@code{.c}
|
||
if (temp > 0.0f) float@myattribute = 0.0f;
|
||
@endcode
|
||
Performs a comparison of this value with @b `0.0f` and, if the value is greater
|
||
than @b `0.0f`, performs a @b write to the geometry in the form of
|
||
<b>`float@myattribute = 0.0f;`</b> which sets the value of this attribute on the
|
||
geometry to @b `0.0f`.
|
||
@par
|
||
For OpenVDB Points, this kernel is run over every point in an OpenVDB Points
|
||
Grid. In simple pseudo code:
|
||
@code{.unparsed}
|
||
foreach(point in pointgrid)
|
||
run_ax_kernel(point)
|
||
done()
|
||
@endcode
|
||
Where @b `pointgrid` is a single Point Data Grid. For OpenVDB volumes the kernel
|
||
is run over each voxel in a provided grid:
|
||
@code{.unparsed}
|
||
foreach(grid in grids)
|
||
foreach(voxel IN grid)
|
||
run_ax_kernel(voxel)
|
||
done()
|
||
done()
|
||
@endcode
|
||
@par
|
||
Where @b `grids` can comprise of any number of OpenVDB volumes. In this program,
|
||
only a floating point grid with the name @b `myattribute` will be updated. Each
|
||
voxel in this grid will have it's value compared in the same way as the points
|
||
example given above.
|
||
|
||
|
||
@subsection axexecutionxcontext OpenVDB Execution Context
|
||
@par
|
||
AX programs are designed to run over different types of grids, specifically
|
||
OpenVDB points and OpenVDB volumes, the latter of which is the set of all default
|
||
supported mathematic volume types in OpenVDB. Programs must be compiled separately
|
||
for points and volumes, or twice to support both (see the @ref vdbaxbinary "vdb_ax binary").
|
||
This is known as compiling for a target <b>Execution Context</b>. There are two
|
||
main considerations to make when switching between execution contexts:
|
||
- Certain @ref axfunctions "functions" may not be available under a given
|
||
context. Some natively supported functions are designed to interface
|
||
directly with geometry attributes, and a further subset of these are tailored
|
||
specifically for point attributes @b or voxel values, not both.
|
||
- Whilst the AX grammar does not change syntactically, @ref axattribaccess
|
||
"attribute accesses" may be affected. This is due to the fundamental
|
||
differences of executing over different types of VDBs/geometry.
|
||
@par Execution over Points
|
||
AX kernels compiled for OpenVDB Points run @b individually on <b>each point</b>
|
||
in every <b>active voxel</b> in a points VDB. Attributes that have been
|
||
accessed in the program are provided such that the program has access to all
|
||
data available on the currently processing point. Multiple OpenVDB Point grids
|
||
can be processed by the same AX program, but only a single OpenVDB Points grid
|
||
can be processed at a time. The default behaviour for AX point programs is to
|
||
process every point which exists in active OpenVDB voxels.
|
||
@par Execution over Volumes
|
||
AX kernels for OpenVDB volumes run individually on every <b>active voxel</b> of
|
||
VDBs which are @b written to (whilst retaining access to all available VDBs).
|
||
Volumes can be thought of as only holding a single "attribute". Whilst points
|
||
hold all attributes within a single VDB points grid (and values for all attributes
|
||
are are defined for all points in that grid), multiple volume attributes require
|
||
multiple VDB volumes to be accessed. The location of this access is the
|
||
<b>world space position</b> of each voxel. Assignment operations determine which
|
||
volumes will be executed over.
|
||
@par
|
||
See the syntax section on @ref axattribaccess "accessing attribute" for more
|
||
information.
|
||
|
||
|
||
<br/><hr>
|
||
|
||
|
||
@section axdatatypes Data Types
|
||
@par
|
||
AX supports a rich variety of native types to be able to maximise the efficiency
|
||
of arithmetic operations and facilitate accessing underlying geometry. As AX is
|
||
designed for OpenVDB, native AX types aim to provide direct access to
|
||
all supported OpenVDB data types. You may find, however, that some AX types do
|
||
not exist as OpenVDB volume/point types or refuse to be serialized in some
|
||
installations of OpenVDB. The table below lists all available types in AX, the
|
||
exposed @ref axattribaccess "attribute access" syntax and whether or not the
|
||
attribute syntax is valid for both point and volume execution contexts.
|
||
Developers installing OpenVDB and OpenVDB AX may wish to read the
|
||
@ref vdbaxtoaxtypes "type registry documentation" which explains how to enable
|
||
missing types from OpenVDB.
|
||
@anchor axdatatypestable
|
||
@par
|
||
<table>
|
||
<tr>
|
||
<th>Category</th><th>Type</th><th>Definition</th><th>Attribute Syntax</th><th>Points</th><th>Voxels</th>
|
||
</tr>
|
||
<tr>
|
||
<td rowspan="7"> @ref axscalars </td>
|
||
<td>`bool`</td>
|
||
<td>Boolean value, true or false</td><td>`bool@`</td>
|
||
<td>@b Yes</td><td>@b Yes</td>
|
||
</tr>
|
||
<tr><td>`int16`*</td><td>16-bit signed integer value</td><td>`int16@`</td><td>@b Yes</td><td>No</td></tr>
|
||
<tr><td>`int32`</td><td>32-bit signed integer value</td><td>`int32@, int@, i@`</td><td>@b Yes</td><td>@b Yes</td></tr>
|
||
<tr><td>`int`</td><td colspan="4">Alias for integer type (typically int32)</td></tr>
|
||
<tr><td>`int64`</td><td>64-bit signed integer value</td><td>`int64@`</td><td>@b Yes</td><td>@b Yes</td></tr>
|
||
<tr><td>`float`</td><td>32-bit floating point value</td><td>`float@ f@ @`</td><td>@b Yes</td><td>@b Yes</td></tr>
|
||
<tr><td>`double`</td><td>64-bit floating point value</td><td>`double@`</td><td>@b Yes</td><td>@b Yes</td></tr>
|
||
<tr>
|
||
<td style="border-top-width: thick" rowspan="9"> @ref axvecmats "Vectors" </td>
|
||
<td style="border-top-width: thick">`vec2i`</td>
|
||
<td style="border-top-width: thick">2-element vector of integer values</td>
|
||
<td style="border-top-width: thick">`vec2i@`</td>
|
||
<td style="border-top-width: thick">No</td>
|
||
<td style="border-top-width: thick">No</td>
|
||
</tr>
|
||
<tr><td>`vec2f`</td><td>2-element vector of float values </td><td>`vec2f@`</td><td>No</td><td>No</td></tr>
|
||
<tr><td>`vec2d`</td><td>2-element vector of double values </td><td>`vec2d@`</td><td>No</td><td>No</td></tr>
|
||
<tr><td>`vec3i`</td><td>3-element vector of integer values</td><td>`vec3i@`</td><td>@b Yes</td><td>@b Yes</td></tr>
|
||
<tr><td>`vec3f`</td><td>3-element vector of float values </td><td>`vec3f@ v@`</td><td>@b Yes</td><td>@b Yes</td></tr>
|
||
<tr><td>`vec3d`</td><td>3-element vector of double values </td><td>`vec3d@`</td><td>@b Yes</td><td>@b Yes</td></tr>
|
||
<tr><td>`vec4i`</td><td>4-element vector of integer values</td><td>`vec4i@`</td><td>No</td><td>No</td></tr>
|
||
<tr><td>`vec4f`</td><td>4-element vector of float values </td><td>`vec4f@`</td><td>No</td><td>No</td></tr>
|
||
<tr><td>`vec4d`</td><td>4-element vector of double values </td><td>`vec4d@`</td><td>No</td><td>No</td></tr>
|
||
<tr>
|
||
<td style="border-top-width: thick" rowspan="4"> @ref axvecmats "Matrices" </td>
|
||
<td style="border-top-width: thick">`mat3f`</td>
|
||
<td style="border-top-width: thick">3x3-matrix of float values </td>
|
||
<td style="border-top-width: thick">`mat3f@` </td>
|
||
<td style="border-top-width: thick">@b Yes</td>
|
||
<td style="border-top-width: thick">No </td>
|
||
<tr><td>`mat3d`</td><td>3x3-matrix of double values</td><td>`mat3d@`</td><td>@b Yes</td><td>No</td></tr>
|
||
<tr><td>`mat4f`</td><td>4x4-matrix of float values </td><td>`mat4f@`</td><td>@b Yes</td><td>No</td></tr>
|
||
<tr><td>`mat4d`</td><td>4x4-matrix of double values</td><td>`mat4d@`</td><td>@b Yes</td><td>No</td></tr>
|
||
<tr>
|
||
<td style="border-top-width: thick" rowspan="1"> @ref axstrings "Strings" </td>
|
||
<td style="border-top-width: thick">`string`</td>
|
||
<td style="border-top-width: thick">A string of characters </td>
|
||
<td style="border-top-width: thick">`string@` </td>
|
||
<td style="border-top-width: thick">@b Yes</td>
|
||
<td style="border-top-width: thick">@b Yes</td>
|
||
</tr>
|
||
</table>
|
||
- @b Note* - There is no support for int16 local variables or integer literals.
|
||
|
||
|
||
@subsection axscalars Scalars
|
||
@par
|
||
AX Supports boolean, integer and floating point scalar types. @b `int` and
|
||
@b `int32` represent 32-bit integer values and @b `int64` represents a 64-bit
|
||
value. @b `float` and @b `double` represent 32-bit and 64-bit floating point
|
||
values respectively. All scalars, excluding bools, are signed; there are no
|
||
other unsigned scalar types in AX.
|
||
@par Integer Overflow and Floating Point Truncation
|
||
Scalars may be cast from one type to another, either explicitly using the
|
||
@ref axopother "cast" operator or implicitly during @ref axopassignment
|
||
"assignments" or @ref axopbinarithmetic "binary arthimetic" operations (in which
|
||
case the order of @ref axtypeprecedence "type precedence" is observed). Data can
|
||
be truncated (converting floats to integrals) or overflow (conversions
|
||
from integers of larger bit widths to integers of smaller bit widths) depending
|
||
on the source and target types. See the below examples:
|
||
@par
|
||
This example demonstrates floating point truncation in AX.
|
||
@code
|
||
float a = 1.1f;
|
||
int b = 5.5f; // implict conversion from literal 5.5f. "b" is set to 5
|
||
b = a; // implicit conversion from float "a". "b" is set to 1
|
||
@endcode
|
||
@par
|
||
This example demonstrates integer overflow in AX.
|
||
@code
|
||
int64 a = 2147483648l; // one more than can be held in an int (note the last letter "l")
|
||
int b = a; // implicit conversion. "b" is set to -2147483648
|
||
@endcode
|
||
@par Infinite and NaN values
|
||
Floating point values have two additional intrinsic states; @b `inf` and @b `nan`.
|
||
These states can occur during invalid floating point arithmetic. AX performs no
|
||
checks on arithmetic to catch these values. A typical example of both @b `inf`
|
||
and @b `nan` values are division by zero expressions:
|
||
@code
|
||
float a = 1.0f/0.0f;
|
||
print(a); // prints "inf"
|
||
@endcode
|
||
@code
|
||
float a = 0.0f/0.0f;
|
||
print(a); // prints some version of "nan"
|
||
@endcode
|
||
@par
|
||
Generally these values are not desired and can cause problems as they propagate
|
||
throughout your program.
|
||
|
||
|
||
@subsection axvecmats Vectors / Matrices
|
||
@par
|
||
All vector and matrix types in AX are implemented as flat arrays of a given size,
|
||
with all elements stored contiguously in memory. Both container types are
|
||
represented by @ref axdatatypestable "specific tokens" which tell AX functions
|
||
and operators how to handle various arithmetic.
|
||
@par Vectors
|
||
There is currently support for vectors of sizes 2, 3 and 4 elements. The suffix
|
||
letter on the vector types denotes the contained elements precision, with the
|
||
number corresponding to the vector size. For example, @b `vec2i` denotes a vector
|
||
of two 32-bit integer elements. There are no native types for vectors with
|
||
@b `bool`, @b `int16` or @b `int64` elements, so these are not supported.
|
||
@par Matrices
|
||
Matrices are stored in row major layout (lexographical access order) which
|
||
matches the representation of a matrix in OpenVDB. Matrix support consists of
|
||
@b `float` and @b `double` precision elements with dimensions either @b `3x3` or
|
||
@b `4x4` (total size of 9 and 16 elements respectively). There are no integer or
|
||
boolean matrix types. Similiar to vectors, the suffix letter on the type denotes
|
||
the contained elements precision, with the number corresponding to the matrix
|
||
dimension. A matrix of type @b `mat3d` therefor corresponds to a @b `3x3` matrix
|
||
(9 elements) with @b `double` precision elements.
|
||
@par Element Access
|
||
As elements of all matrix and vector types are stored contiguously, they can be
|
||
accessed by the @ref axvecaccessop "[] operator". Vector elements can also be
|
||
accessed by supported @ref axopaccess ". operator" components and matrix
|
||
elements can be accessed with the @ref axmataccessop "[,] operator".
|
||
@par Initialization
|
||
Both matrices and vector declarations can be flat initialized from scalars or
|
||
component initialized from containers of the same size (see @ref axopassignment
|
||
"assignments"). However both types can also be represented as temporary containers
|
||
without declarations using the @ref axvecmatinit "{,} syntax."
|
||
@par A Note on Operators
|
||
Most @ref axopbinary "binary operators" only accept vectors of @b equal sizes as
|
||
valid left and right operands - however there exists valid @ref axopbinarithmetic
|
||
"arithmetic" for combinations of vectors/matrices with scalars and, importantly,
|
||
@ref axbinmultop "multiplicative arithmetic" for vectors with matrices, the latter
|
||
performing matrix projections (transformations) on vector arguments.
|
||
|
||
|
||
@subsection axstrings Strings
|
||
@par
|
||
Strings are an array of characters stored in a unique AX type which is
|
||
incompatible with @ref axopaccess "container accesses". As such, string support
|
||
is currently fairly limited. Characters themselves (users may know this as a
|
||
@b `char` type) have no frontend type, so a @b `string` type must be used for
|
||
any number of characters (including the empty string). String literals are
|
||
represented by enclosing any number of @ref axtokens "supported AX characters"
|
||
by quotes <b>\" \"</b>.
|
||
|
||
@subsection axtypeprecedence Implicit conversion / type precedence
|
||
@par
|
||
All operators that perform on two or more types must internally run the
|
||
operation at a single precision. When mixing different types (e.g. `int +
|
||
float`) values may need to be converted to another type before the operation is
|
||
performed. To allow for easier writing of expressions, AX will automatically
|
||
detect these cases and convert values when necessary. This is known as
|
||
<b>implicit type conversion</b> and the way in which the target operation type
|
||
is chosen is known as <b>type precedence</b>.
|
||
@par
|
||
When referring to type precedence, we are primarily refering to the conversion of
|
||
one @b scalar type to another. For vectors, matrices and other containers, this
|
||
refers to the conversion of their element type e.g. `mat3f` to `mat3d`. The
|
||
conversion rules for more than the element type (e.g. `int` to `mat4f`) are
|
||
governed by AX's assignment and operator rules, detailed in the @ref axoperators
|
||
section of this documentation.
|
||
@par
|
||
Type precedence @b only applies to the @b element type of the type in question.
|
||
Containers (such as vectors or matrices) may change their element type precision
|
||
(e.g. `vec2i` to `vec2f`). Each scalar type has a ranking which is compared, and
|
||
the resulting highest rank is chosen as the target type for all values. These
|
||
rankings are defined as follows:
|
||
- If any element types are of type `double`, all other element types are converted to `double`
|
||
- else, if any element types are of type `float`, all other element types are converted to `float`
|
||
- else, if any element types are of type `int64`, all other element types are converted to `int64`
|
||
- else, if any element types are of type `int32`, all other element types are converted to `int32`
|
||
- else, all element types are `bool`
|
||
@par
|
||
For example:
|
||
@par
|
||
<!-- A -->@code{.c}
|
||
int a = 0;
|
||
float b = 0.0f;
|
||
// In the following, the arithmetic a + b chooses floating point precision as
|
||
// defined by the above type precedence rules (i.e. float(a) + b). The temporary
|
||
// value created by the arithmetic + will be at float precision. The subsequent
|
||
// assignment must then convert the final result back an integer, resulting in
|
||
// an expression equal to: a = int(float(a) + b);
|
||
a = a + b;
|
||
|
||
// This example shows arithmetic minus with a float scalar and vec4d. Minus is a
|
||
// supported operator of vec4d, however as the element types do not match
|
||
// (float vs double), implicit conversion must be observed. With the above rules,
|
||
// we can determine the following expression: c = double(b) + c. Note that
|
||
// as the result of "double(b) + c" is a vec4d and the target of the subsequent
|
||
// assignment ("c") is a vec4d, no further conversion needs to be performed.
|
||
vec4d c = 0.0; // double element type
|
||
c = b - c;
|
||
@endcode
|
||
@par
|
||
Strings are not included in this precedence as there are no supported arithmetic
|
||
binary operations for strings with operand types other than string.
|
||
|
||
<br/><hr>
|
||
|
||
@section axoperators Operators
|
||
@par
|
||
The below table lists all available operators supported by AX. Note that not all
|
||
AX types support all operators and some operators have unique functionality
|
||
depending on the operand types.
|
||
@par
|
||
<table>
|
||
<tr style="text-align:center">
|
||
<th colspan="9"> Operators
|
||
</th></tr>
|
||
<tr style="text-align:center">
|
||
<td bgcolor="#ffc4c4" style="border-right-width: thick" colspan="4"> @ref axopbinary </td>
|
||
<td bgcolor="#ffc4c4" style="border-right-width: thick" colspan="3"> @ref axopunary </td>
|
||
<td bgcolor="#ffc4c4" colspan="2"> Other </td></tr>
|
||
<tr style="text-align:center">
|
||
<td> @ref axopassignment </td>
|
||
<td> @ref axopbinarithmetic </td>
|
||
<td> @ref axopcomparison </td>
|
||
<td style="border-right-width: thick"> @ref axopbinlogical </td>
|
||
<td> @ref axopunarithmetic </td>
|
||
<td> @ref axopunlogical </td>
|
||
<td style="border-right-width: thick"> @ref axopunincdec </td>
|
||
<td> @ref axopaccess </td>
|
||
<td> @ref axopother </td></tr>
|
||
<tr style="text-align:center">
|
||
<td><p> <!-- *********************** COLUMN ASSIGNMENT *********************** -->
|
||
<code>
|
||
a = b<br/>a += b<br/>a -= b<br/>a *= b<br/>a /= b<br/>a %= b<br/>
|
||
a &= b<br/>a |= b<br/>a ^= b<br/>a <<= b<br/>a >>= b
|
||
</code>
|
||
</p></td>
|
||
<td><p> <!-- *********************** COLUMN ARITH *********************** -->
|
||
<code>
|
||
a + b<br/>a - b<br/>a * b<br/>a / b<br/>a % b<br/>a & b<br/>a | b<br/>
|
||
a ^ b<br/>a << b<br/>a >> b
|
||
</code></p></td>
|
||
<td><p> <!-- *********************** COLUMN COMP *********************** -->
|
||
<code>
|
||
a == b<br/>a != b<br/>a < b<br/>a > b<br/>a <= b<br/>a >= b
|
||
</code>
|
||
</p></td>
|
||
<td style="border-right-width: thick"><p> <!-- *********************** COLUMN LOGICAL *********************** -->
|
||
<code>
|
||
a && b<br/>a || b
|
||
</code>
|
||
</p></td>
|
||
<td><p> <!-- *********************** COLUMN ARITH *********************** -->
|
||
<code>
|
||
+a<br/>-a<br/>~a
|
||
</code>
|
||
</p></td>
|
||
<td><p> <!-- *********************** COLUMN LOGICAL *********************** -->
|
||
<code>
|
||
!a
|
||
</code>
|
||
</p></td>
|
||
<td style="border-right-width: thick"><p> <!-- *********************** COLUMN INC/DEC *********************** -->
|
||
<code>
|
||
++a<br/>\-\-a<br/>a++<br/>a\-\-
|
||
</code>
|
||
</p></td>
|
||
<td><p> <!-- *********************** COLUMN OTHER *********************** -->
|
||
<code>
|
||
a[]<br/>a[,]<br/>a.b
|
||
</code>
|
||
</p></td>
|
||
<td><p> <!-- *********************** COLUMN OTHER *********************** -->
|
||
<code>
|
||
a(...)<br/>a, b<br/>a ? b : c<br/>{ a,b ... }
|
||
</code>
|
||
</p></td>
|
||
</tr>
|
||
</table>
|
||
|
||
|
||
@subsection axopbinary Binary Operators
|
||
@par
|
||
Binary operators are the most common inbuilt operators for AX types. These
|
||
operators take two inputs; a left hand side and a right hand side. There exists
|
||
a number of valid combinations of AX types with different binary operators, as
|
||
well as different implicit casting schemes depending on the binary operation
|
||
being performed.
|
||
|
||
|
||
@subsubsection axopassignment Assignments
|
||
@par
|
||
Assignment operators are the only way to directly modify the value of local and
|
||
external data (except for @ref axfunctions which take @b references). The
|
||
assignment operators have the following forms:
|
||
@par
|
||
<table>
|
||
<tr><th>Operator Name</th><th>Operator Syntax</th><th>Returns</th></tr>
|
||
<tr><td>Simple assignment</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`=`</b> @a `rhs` </td><td>Reference to @a `lhs`</td></tr>
|
||
<tr><td>Addition assignment</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`+=`</b> @a `rhs` </td><td>Reference to @a `lhs`</td></tr>
|
||
<tr><td>Subtraction assignment</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`-=`</b> @a `rhs` </td><td>Reference to @a `lhs`</td></tr>
|
||
<tr><td>Multiplication assignment</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`*=`</b> @a `rhs` </td><td>Reference to @a `lhs`</td></tr>
|
||
<tr><td>Division assignment</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`/=`</b> @a `rhs` </td><td>Reference to @a `lhs`</td></tr>
|
||
<tr><td>Modulo assignment</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`%=`</b> @a `rhs` </td><td>Reference to @a `lhs`</td></tr>
|
||
<tr><td>Bitwise AND assignment</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`&=`</b> @a `rhs` </td><td>Reference to @a `lhs`</td></tr>
|
||
<tr><td>Bitwise OR assignment</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`|=`</b> @a `rhs` </td><td>Reference to @a `lhs`</td></tr>
|
||
<tr><td>Bitwise XOR assignment</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`^=`</b> @a `rhs` </td><td>Reference to @a `lhs`</td></tr>
|
||
<tr><td>Bitwise shift left assignment</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`<<=`</b> @a `rhs` </td><td>Reference to @a `lhs`</td></tr>
|
||
<tr><td>Bitwise shift right assignment</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`>>=`</b> @a `rhs` </td><td>Reference to @a `lhs`</td></tr>
|
||
</table>
|
||
@par
|
||
These can be further categorised into two types; direct assignment, which is
|
||
comprised only of the <b>simple assignment</b> operator, and compound assignments,
|
||
which is the set of all other assignment operators.
|
||
@par Direct Assignment
|
||
Direct assignments replace the contents of the @b `lhs` with a copy of the @b
|
||
`rhs`:
|
||
@par
|
||
<table><tr>
|
||
<td bgcolor="#ffc4c4"> @a `lhs` <b>= </b> @a `rhs` </td>
|
||
</tr></table>
|
||
@par
|
||
The @b `rhs` side is not modified and the @b `lhs` is not read - only written
|
||
to. If the @b `rhs` type does not match the @b `lhs` type, the @b `rhs` is first
|
||
implicitly converted into a new temporary with the @b `lhs` type before being
|
||
copied into the @b `lhs`. The following combination of AX type categories are
|
||
supported for direct assignment (if an operation is not listed, it is not
|
||
supported):
|
||
@par
|
||
<table>
|
||
<tr style="text-align:center">
|
||
<th>Left Operand Type</th><th>Binary Op(s)</th><th>Right Operand Type</th><th>Description</th>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td rowspan="1">@ref axscalars "scalar"</td><td rowspan="1">`=`</td>
|
||
<td>@ref axscalars "scalar"</td>
|
||
<td style="text-align:left">On type mismatch, right hand side is copied and
|
||
@ref axtypeprecedence "implicitly cast" to the left hand side type.</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td style="border-top-width: thick" rowspan="2">@ref axvecmats "vector"</td>
|
||
<td style="border-top-width: thick; text-align:center" rowspan="2">`=`</td>
|
||
<td style="border-top-width: thick">@ref axscalars "scalar"</td>
|
||
<td style="border-top-width:thick;text-align:left">
|
||
Each element of the vector is set to the right hand side scalar. i.e.
|
||
<br/> `a[0] = b; ... a[n-1] = b;` <br/>
|
||
where `n` is the size of the vector. If the scalar type does not match
|
||
element type of vector, the scalar is copied and @ref axtypeprecedence
|
||
"implicitly cast" to that type.</td>
|
||
</tr>
|
||
<tr style="text-align:center"><td>@ref axvecmats "vector"</td>
|
||
<td style="text-align:left">Component wise assignment i.e.
|
||
<br/> `a[0] = b; ... a[n-1] = b;` <br/>
|
||
where `n` is the size of the vector.
|
||
<!-- A -->@code{.c}
|
||
vec3f a = 0, b = 1;
|
||
a = b;
|
||
@endcode
|
||
is equal to:
|
||
<!-- A -->@code{.c}
|
||
vec3f a = 0, b = 1;
|
||
for (int i = 0; i < 3; ++i) a[i] = b[i];
|
||
@endcode
|
||
If the right hand side element type does not
|
||
match the left hand side element type, each element of the right hand side is
|
||
copied and @ref axtypeprecedence "implicitly cast "to the target left hand side
|
||
element type.
|
||
<b>Operand sizes must match.</b></td>
|
||
<tr style="text-align:center">
|
||
<td style="border-top-width: thick" rowspan="2">@ref axvecmats "matrix"</td>
|
||
<td style="border-top-width: thick;text-align:center" rowspan="2">`=`</td>
|
||
<td style="border-top-width: thick">@ref axscalars "scalar"</td>
|
||
<td style="border-top-width:thick;text-align:left">
|
||
Diagonal matrix construction. Each diagonal component of the left hand side
|
||
matrix is set to to the right hand side scalar. All other components are zero
|
||
initialized i.e.
|
||
<!-- A -->@code{.c}
|
||
mat3f a;
|
||
int dim = 3, b = 1;
|
||
for (int i = 0; i < dim; ++i)
|
||
a[i] = (i % (dim+1) == 0) ? b : 0;
|
||
@endcode
|
||
Where `a` is the matrix, `dim` is the dimension of the matrix (e.g. 3 for
|
||
`mat3f`) and `b` is the scalar. If the scalar type does not match element type
|
||
of matrix, the scalar is copied and @ref axtypeprecedence "implicitly cast" to
|
||
that type.</td>
|
||
<tr style="text-align:center"><td>@ref axvecmats "matrix"</td>
|
||
<td style="text-align:left">Component wise assignment i.e.
|
||
<br/> `a[0] = b[0]; ... a[n-1] = b[n-1];` <br/>
|
||
where `n` is the @b total size of the matrix.
|
||
<!-- A -->@code{.c}
|
||
mat4f a = 0, b = 1;
|
||
a = b;
|
||
@endcode
|
||
is equal to:
|
||
<!-- A -->@code{.c}
|
||
mat4f a = 0, b = 1;
|
||
for (int i = 0; i < 16; ++i) a[i] = b[i];
|
||
@endcode
|
||
If the right hand side element type does not match the left hand side element
|
||
type, each element of the right hand side is copied and @ref axtypeprecedence
|
||
"implicitly cast" to the target left hand side element type.
|
||
<b>Operand sizes must match.</b></td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td style="border-top-width: thick">@ref axstrings "string"</td>
|
||
<td style="border-top-width: thick;text-align:center">`=`</td>
|
||
<td style="border-top-width: thick">@ref axstrings "string"</td>
|
||
<td style="border-top-width: thick;text-align:left">Replaces the contents of the
|
||
left hand side string with a copy of the contents in the right hand side string.
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
@par
|
||
<!-- A -->@code{.c}
|
||
float b;
|
||
vec3f c = 0.0f; // assign components of c (x/y/z) to an floating point literal of value 0.0f
|
||
int a = 1; // assign a from an integer literal of value 1
|
||
c = a; // assign components of c (x/y/z) to the result of float(a)
|
||
@endcode
|
||
@par Compound Assignment
|
||
Compound assignments replace the the contents of the @b `lhs` with the result of
|
||
a @ref axopbinarithmetic "binary arithmetic" operation of the @b `lhs` with the
|
||
@b `rhs`:
|
||
@par
|
||
<table>
|
||
<tr><td bgcolor="#ffc4c4"> @a `lhs` @b op @a `rhs` </td></tr>
|
||
</table>
|
||
Where @b op is one of :
|
||
<table><tr>
|
||
<td bgcolor="#ffc4c4"> <b>`+=`</b></td>
|
||
<td bgcolor="#ffc4c4"> <b>`-=`</b></td>
|
||
<td bgcolor="#ffc4c4"> <b>`*=`</b></td>
|
||
<td bgcolor="#ffc4c4"> <b>`/=`</b></td>
|
||
<td bgcolor="#ffc4c4"> <b>`%=`</b></td>
|
||
<td bgcolor="#ffc4c4"> <b>`&=`</b></td>
|
||
<td bgcolor="#ffc4c4"> <b>`|=`</b></td>
|
||
<td bgcolor="#ffc4c4"> <b>`^=`</b></td>
|
||
<td bgcolor="#ffc4c4"> <b>`<<=`</b></td>
|
||
<td bgcolor="#ffc4c4"> <b>`>>= `</b></td>
|
||
</tr></table>
|
||
@par
|
||
The behaviour of a given compound assignment (for example `a += b`) is similar
|
||
to replacing the compound assignment with a @ref axopassignment
|
||
"direct assignment" followed by a @ref axopbinarithmetic "binary expression"
|
||
with the same operands and given arithmetic token (i.e. `a = a + b`). However,
|
||
compound assignments imporantly do @b not evaluate the @b `lhs` twice. This is
|
||
important when assigning to an expression which is not an attribute or local
|
||
value. The best example of this is assigning to a @ref axopunincdec "pre-crement"
|
||
operation:
|
||
@par
|
||
<!-- A -->@code{.c}
|
||
int a = 1;
|
||
++a += 1; // equal to a = ++a + 1 which is equal to 3
|
||
@endcode
|
||
@par
|
||
The @b `rhs` side is not modified, however the @b `lhs` is both read from and
|
||
written to. Note that the arithmetic operation may cast either @b `lhs` or @b
|
||
`rhs` following the rules of AX's @ref axopbinarithmetic
|
||
"arithmetic type precedence". See the @ref axopbinarithmetic
|
||
"arithmetic operations" section for more information on arithmetic type
|
||
precedence and explanations on the above compound operators.
|
||
@par
|
||
<!-- A -->@code{.c}
|
||
int a = 3;
|
||
a += a; // the same as a = a + a; a will be set to 6
|
||
float b = 0;
|
||
b -= a; // the same as b = b - float(a);
|
||
a *= b; // the same as a = float(a) * b; Note that although the target type is int, the binary op is performed at float precision
|
||
@endcode
|
||
@par Assignment Chains
|
||
As assignments return a @b reference to the left hand side, all assignment
|
||
operators can be @b chained. Note however that the return result will be at the
|
||
type of the left hand side. For example:
|
||
@par
|
||
Given
|
||
@par
|
||
<!-- A -->@code{.c}
|
||
float a;
|
||
int b, c;
|
||
@endcode
|
||
@par
|
||
This
|
||
@par
|
||
@code{.c}
|
||
a = b = c = 4.5f;
|
||
@endcode
|
||
@par
|
||
is fundamentally the same as:
|
||
@par
|
||
@code{.c}
|
||
c = 4.5f; // c of type int. 4.5f will be floored (int(4.5)). c becomes 4
|
||
b = c; // b becomes 4
|
||
a = b; // a becomes float(4)
|
||
@endcode
|
||
@par
|
||
Importantly, @b `a` receives the result of any previous implicit casts to the
|
||
right hand side of its binary assignment.
|
||
|
||
|
||
@subsubsection axopbinarithmetic Arithmetic
|
||
@par
|
||
Binary arithmetic operations compute the result of a arithmetic operand token on
|
||
two inputs and returns the result. The inputs are not modified, however may be
|
||
copied and @ref axtypeprecedence "implicitly cast" to temporary values if the
|
||
types do not match. All results are returned as new temporary values. If
|
||
@b integral is explicitly stated, the operation is only valid on types which
|
||
have an integer element type and will involve and implicit cast to integer types
|
||
for floating point operands (the operation may be further restricted for
|
||
container types). Binary arithmetic operations have the following forms:
|
||
@par
|
||
<table>
|
||
<tr><th>Operator Name</th><th>Operator Syntax</th><th>Returns</th></tr>
|
||
<tr><td>Addition</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`+`</b> @a `rhs` </td><td>The sum of both operands</td></tr>
|
||
<tr><td>Subtraction</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`-`</b> @a `rhs` </td><td>The first operand minus the second operand</td></tr>
|
||
<tr><td>Multiplication</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`*`</b> @a `rhs` </td><td>The product of both operands</td></tr>
|
||
<tr><td>Division</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`/`</b> @a `rhs` </td><td>The first operand divided by the second operand</td></tr>
|
||
<tr><td>Modulo</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`%`</b> @a `rhs` </td><td>The @b floored modulo operator. See @ref axbinmultop "Multiplicative operands"</td></tr>
|
||
<tr><td>Bitwise AND</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`&`</b> @a `rhs` </td>
|
||
<td>The @b integral bitwise AND result of each bit in the first operand applied to the bit at the same location in the second operand</td></tr>
|
||
<tr><td>Bitwise OR</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`|`</b> @a `rhs` </td>
|
||
<td>The @b integral bitwise OR result of each bit in the first operand applied to the bit at the same location in the second operand</td></tr>
|
||
<tr><td>Bitwise XOR</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`^`</b> @a `rhs` </td>
|
||
<td>The @b integral bitwise XOR result of each bit in the first operand applied to the bit at the same location in the second operand</td></tr>
|
||
<tr><td>Bitwise shift left</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`<<`</b> @a `rhs` </td>
|
||
<td>The @b integral bitwise left shift of the first operand by the second operand</td></tr>
|
||
<tr><td>Bitwise shift right</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`>>`</b> @a `rhs` </td>
|
||
<td>The @b integral bitwise right shift of the first operand by the second operand</td></tr>
|
||
</table>
|
||
@anchor axbinadditiveop
|
||
@par Additive operands
|
||
Binary additive operations perform summations on the input arguments. They have
|
||
the following forms:
|
||
@par
|
||
<table>
|
||
<tr><td bgcolor="#ffc4c4"> @a `lhs` @b `+` @a `rhs` </td></tr>
|
||
<tr><td bgcolor="#ffc4c4"> @a `lhs` @b `-` @a `rhs` </td></tr>
|
||
</table>
|
||
@par
|
||
After @ref axtypeprecedence "implicit conversion", the result of the binary
|
||
operation with the arithmetic @b `+` (@ref axtokens "plus token") is the sum of
|
||
the operands, and the result of the binary operation with the arithmetic @b `-`
|
||
(@ref axtokens "minus token") token is the second operand subtracted from the
|
||
first operand. The following combination of AX type categories are supported for
|
||
additive operations (if an operation is not listed, it is not supported):
|
||
@par
|
||
<table>
|
||
<tr style="text-align:center">
|
||
<th>Left Operand Type</th><th>Binary Op(s)</th><th>Right Operand Type</th><th>Description</th>
|
||
</tr>
|
||
<tr style="text-align:center"><td rowspan="3">@ref axscalars "scalar"</td><td rowspan="3">`+` `-`</td><td>@ref axscalars "scalar"</td>
|
||
<td style="text-align:left">Returns the result of the scalar addition or subtraction.</td>
|
||
</tr>
|
||
<tr style="text-align:center"><td>@ref axvecmats "vector"</td>
|
||
<td style="text-align:left" rowspan="2">Performs per component binary operations
|
||
(after @ref axtypeprecedence "implicit conversion") with the left hand side
|
||
scalar to every element of the right hand side vector or matrix, returning a
|
||
vector or matrix.
|
||
<!-- A -->@code{.c}
|
||
vec3f a = 2.0f;
|
||
int b = 1;
|
||
vec3f c = b + a;
|
||
@endcode
|
||
is equal to:
|
||
<!-- A -->@code{.c}
|
||
vec3f a = 2.0f;
|
||
int b = 1;
|
||
vec3f c;
|
||
for (int i = 0; i < 3; ++i) c[i] = b + a[i];
|
||
@endcode
|
||
</td>
|
||
</tr>
|
||
<tr style="text-align:center"><td>@ref axvecmats "matrix"</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td style="border-top-width: thick" rowspan="2">@ref axvecmats "vector"</td>
|
||
<td style="border-top-width: thick; text-align:center" rowspan="2">`+` `-`</td>
|
||
<td style="border-top-width: thick">@ref axscalars "scalar"</td>
|
||
<td style="border-top-width: thick;text-align:left">Same as `scalar op vector`</td>
|
||
</tr>
|
||
<tr style="text-align:center"><td>@ref axvecmats "vector"</td>
|
||
<td style="text-align:left">Performs per component binary operations (after
|
||
@ref axtypeprecedence "implicit conversion"), returning a new vector with each
|
||
element holding the corresponding result. <b>Operand sizes must match.</b>
|
||
<!-- A -->@code{.c}
|
||
vec3f a = 2, b = 1;
|
||
vec3f c = a - b;
|
||
@endcode
|
||
is equal to:
|
||
<!-- A -->@code{.c}
|
||
vec3f a = 2, b = 1;
|
||
vec3f c;
|
||
for (int i = 0; i < 3; ++i) c[i] = a[i] - b[i];
|
||
@endcode
|
||
</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td style="border-top-width: thick" rowspan="2">@ref axvecmats "matrix"</td>
|
||
<td style="border-top-width: thick;text-align:center" rowspan="2">`+` `-`</td>
|
||
<td style="border-top-width: thick">@ref axscalars "scalar"</td>
|
||
<td style="border-top-width: thick;text-align:left">Same as `scalar op matrix`</td>
|
||
</tr>
|
||
<tr style="text-align:center"><td>@ref axvecmats "matrix"</td>
|
||
<td style="text-align:left">Performs per component binary operations (after
|
||
@ref axtypeprecedence "implicit conversion"), returning a new matrix with each
|
||
element holding the corresponding result. <b>Operand sizes must match.</b>
|
||
<!-- A -->@code{.c}
|
||
mat4f a = 0, b = 1;
|
||
mat4f c = a - b;
|
||
@endcode
|
||
is equal to:
|
||
<!-- A -->@code{.c}
|
||
mat4f a = 0, b = 1;
|
||
mat4f c;
|
||
for (int i = 0; i < 16; ++i) c[i] = a[i] - b[i];
|
||
@endcode
|
||
</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td style="border-top-width: thick">@ref axstrings "string"</td>
|
||
<td style="border-top-width: thick;text-align:center">`+`</td>
|
||
<td style="border-top-width: thick">@ref axstrings "string"</td>
|
||
<td style="border-top-width: thick;text-align:left">Performs string concatenation</td>
|
||
</tr>
|
||
</table>
|
||
@note
|
||
Floating point addition and subtraction is communicative (`a + b = b + a`) but
|
||
is not @b necessarily associative. i.e. `(a + b) + c` is not necessarily equal
|
||
to `a + (b + c)`.
|
||
@par
|
||
Examples of validity of additive operations:
|
||
@par
|
||
@code{.c}
|
||
int a = 0;
|
||
vec2f b = 1.0f;
|
||
vec2i c = 2;
|
||
mat4d d = 0.0;
|
||
c + a; // valid vec + scalar
|
||
c + d; // invalid vec + matrix
|
||
c - b; // valid vec - scalar
|
||
@endcode
|
||
@anchor axbinmultop
|
||
@par Multiplicative operands
|
||
The binary multiplicative operands have the following forms:
|
||
@par
|
||
<table>
|
||
<tr><td bgcolor="#ffc4c4"> @a `lhs` @b `*` @a `rhs` </td></tr>
|
||
<tr><td bgcolor="#ffc4c4"> @a `lhs` @b `/` @a `rhs` </td></tr>
|
||
<tr><td bgcolor="#ffc4c4"> @a `lhs` @b `%` @a `rhs` </td></tr>
|
||
</table>
|
||
@par
|
||
After @ref axtypeprecedence "implicit conversion", the result of the binary
|
||
operation:
|
||
- with the arithmetic @b `*` (@ref axtokens "asterisk token") is:
|
||
- the product of the operands
|
||
- @b OR performs matrix multiplication for vector and matrix types.
|
||
- with the arithmetic @b `/` (@ref axtokens "forward slash token") is the first
|
||
operand divided by the second operand.
|
||
- with the arithmetic @b `%` (@ref axtokens "percentage token") is the
|
||
@b floored modulo operations .i.e. the expression `d % D` returns the result
|
||
`D - d * floor(D/d)`. This is in contrast to truncated modulo operations
|
||
`D - d * (D/d)` where the division is truncated.
|
||
@warning
|
||
Floored modulo has been chosen to provide better expected behaviour with signed
|
||
dividends. In such cases the result will always be positive; in other words,
|
||
the sign of the result is @b always taken from the divisor. This does however
|
||
mean that the relationship properties between `%` and `/` differ when either
|
||
@b `d` or @b `D` is negative. i.e.:
|
||
`(d/D)*D + (d%D) != d`
|
||
@note
|
||
The multiplicative operation @b `*` has important behaviour for vectors and
|
||
matrix types.
|
||
@par
|
||
The following combination of AX type categories are supported for multiplicative
|
||
operations (if an operation is not listed, it is not supported):
|
||
@par
|
||
<table>
|
||
<tr style="text-align:center">
|
||
<th>Left Operand Type</th><th>Binary Op(s)</th><th>Right Operand Type</th><th>Description</th>
|
||
</tr>
|
||
<tr style="text-align:center"><td rowspan="3">@ref axscalars "scalar"</td><td rowspan="2">`* / %`</td><td rowspan="1">@ref axscalars "scalar"</td>
|
||
<td style="text-align:left">Returns the result of the scalar multiplication, division or remainder of the division respectively. </td>
|
||
</tr>
|
||
<tr style="text-align:center"><td>@ref axvecmats "vector"</td></td>
|
||
<td style="text-align:left" rowspan="1">
|
||
Performs per component binary operations (after
|
||
@ref axtypeprecedence "implicit conversion") with the left hand side scalar to
|
||
every element of the right hand side vector. The scalar is effectively treated
|
||
as a vector of the same size as the right hand side type.
|
||
<!-- A -->@code{.c}
|
||
vec3f a = 2.0f;
|
||
int b = 1;
|
||
vec3f c = b * a;
|
||
@endcode
|
||
is equal to:
|
||
<!-- A -->@code{.c}
|
||
vec3f a = 2.0f;
|
||
int b = 1;
|
||
vec3f c;
|
||
for (int i = 0; i < 3; ++i) c[i] = b * a[i];
|
||
@endcode
|
||
</td>
|
||
</tr>
|
||
<tr style="text-align:center"><td rowspan="1">`*`</td><td>@ref axvecmats "matrix"</td>
|
||
<td style="text-align:left" rowspan="1">
|
||
Performs matrix multiplication after diagonal matrix construction from the left
|
||
hand side scalar.
|
||
<!-- A -->@code{.c}
|
||
mat3f a = 1;
|
||
float b = 1;
|
||
mat3f c = a * b;
|
||
@endcode
|
||
is equal to:
|
||
<!-- A -->@code{.c}
|
||
mat3f a = 1;
|
||
float b = 1;
|
||
mat3f tmp = b; // diagonal matrix
|
||
mat3f c = a * tmp;
|
||
@endcode
|
||
</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td style="border-top-width: thick" rowspan="3">@ref axvecmats "vector"</td>
|
||
<td style="border-top-width: thick; text-align:center" rowspan="2">`* / %`</td>
|
||
<td style="border-top-width: thick">@ref axscalars "scalar"</td>
|
||
<td style="border-top-width: thick;text-align:left">Same as `scalar op vector`
|
||
with the operands reversed (importantly for division and modulus)</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td>@ref axvecmats "vector"</td>
|
||
<td style="text-align:left">Performs per component binary operations (after
|
||
@ref axtypeprecedence "implicit conversion"), returning a new vector with each
|
||
element holding the corresponding result. <b>Operand sizes must match.</b>
|
||
<!-- A -->@code{.c}
|
||
vec3f a = 2, b = 1;
|
||
vec3f c = a * b;
|
||
@endcode
|
||
is equal to:
|
||
<!-- A -->@code{.c}
|
||
vec3f a = 2, b = 1;
|
||
vec3f c;
|
||
for (int i = 0; i < 3; ++i) c[i] = a[i] * b[i];
|
||
@endcode
|
||
</td>
|
||
</tr>
|
||
<tr style="text-align:center"><td>`*`</td><td>@ref axvecmats "matrix"</td>
|
||
<td style="text-align:left">
|
||
Transforms the left hand side vector by the right hand side matrix using matrix
|
||
multiplication. This is the same as calling the @ref axtransform "transform"
|
||
function. e.g:
|
||
<!-- A -->@code{.c}
|
||
mat4f a = identity4();
|
||
vec3f b = { 1, 2, 3 };
|
||
b = b * a;
|
||
@endcode
|
||
is equal to:
|
||
<!-- A -->@code{.c}
|
||
mat4f a = identity4();
|
||
vec3f b = { 1, 2, 3 };
|
||
b = transform(b, a);
|
||
@endcode
|
||
Typically, matrix multiplication requires arguments of the same dimension sizes -
|
||
that is, a `mat4` can only be applied to a `vec4`. However, it is often useful to
|
||
be able to directly apply `mat4` transformations to `vec3` types, most often due
|
||
to positions being represented as `vec3`. `vec3 * mat4` multiplication is
|
||
supported, where by the `vec3` is extended with a `1` component and the
|
||
resulting last last component is dropped from the return
|
||
value:
|
||
<!-- A -->@code{.c}
|
||
mat4f a = identity4();
|
||
vec3f b = { 1, 2, 3 };
|
||
// b * a is equal to:
|
||
vec4f tmp;
|
||
tmp[0] = b[0];
|
||
tmp[1] = b[1];
|
||
tmp[2] = b[2];
|
||
tmp[3] = 1;
|
||
tmp = tmp * a;
|
||
b[0] = tmp[0];
|
||
b[1] = tmp[1];
|
||
b[2] = tmp[2];
|
||
@endcode
|
||
@b Note: Valid operand sizes and return types match those of the
|
||
@ref axtransform "transform" function i.e:
|
||
- `vec3 * mat3 = vec3`
|
||
- `vec3 * mat4 = vec3`
|
||
- `vec4 * mat4 = vec4`
|
||
</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td style="border-top-width: thick" rowspan="3">@ref axvecmats "matrix"</td>
|
||
<td style="border-top-width: thick;text-align:center" rowspan="3">`*`</td>
|
||
<td style="border-top-width: thick">@ref axscalars "scalar"</td>
|
||
<td style="border-top-width: thick;text-align:left">Same as `scalar * matrix`</td>
|
||
</tr>
|
||
<tr style="text-align:center"><td>@ref axvecmats "vector"</td>
|
||
<td style="text-align:left">
|
||
Transforms the right hand side vector by the left hand side matrix using matrix
|
||
multiplication. This is the same as calling the @ref axpretransform "pretransform"
|
||
function. e.g:
|
||
<!-- A -->@code{.c}
|
||
mat4f a = identity4();
|
||
vec3f b = { 1, 2, 3 };
|
||
b = a * b;
|
||
@endcode
|
||
is equal to:
|
||
<!-- A -->@code{.c}
|
||
mat4f a = identity4();
|
||
vec3f b = { 1, 2, 3 };
|
||
b = pretransform(a, b);
|
||
@endcode
|
||
Typically, matrix multiplication requires arguments of the same dimension sizes -
|
||
that is, a `mat4` can only be applied to a `vec4`. However, it is often useful to
|
||
be able to directly apply `mat4` transformations to `vec3` types, most often due
|
||
to positions being represented as `vec3`. `mat4 * vec3` multiplication is
|
||
supported, where by the `vec3` is extended with a `1` component and the
|
||
resulting last last component is dropped from the return
|
||
value:
|
||
<!-- A -->@code{.c}
|
||
mat4f a = identity4();
|
||
vec3f b = { 1, 2, 3 };
|
||
// a * b is equal to:
|
||
vec4f tmp;
|
||
tmp[0] = b[0];
|
||
tmp[1] = b[1];
|
||
tmp[2] = b[2];
|
||
tmp[3] = 1;
|
||
tmp = a * tmp;
|
||
b[0] = tmp[0];
|
||
b[1] = tmp[1];
|
||
b[2] = tmp[2];
|
||
@endcode
|
||
@b Note: Valid operand sizes and return types match those of the
|
||
@ref axpretransform "pretransform" function i.e:
|
||
- `mat3 * vec3 = vec3`
|
||
- `mat4 * vec3 = vec3`
|
||
- `mat4 * vec4 = vec4`
|
||
</td>
|
||
</tr>
|
||
<tr style="text-align:center"><td>@ref axvecmats "matrix"</td>
|
||
<td style="text-align:left">
|
||
Performs matrix multiplication and returns the matrix product, which is matrix
|
||
of matchign size and type. <b>Operand sizes must match.</b> e.g:
|
||
<!-- A -->@code{.c}
|
||
mat4f a = 1, b = 2;
|
||
mat4f c = a * b;
|
||
@endcode
|
||
is equal to:
|
||
<!-- A -->@code{.c}
|
||
mat4f a = 1, b = 2;
|
||
mat4f c;
|
||
for(int i = 0; i < 4; ++i) {
|
||
for(int j = 0; j < 4; ++j) {
|
||
for(int k = 0; k < 4; ++k) {
|
||
c[i,j] += a[i,k] * b[k,j];
|
||
}
|
||
}
|
||
}
|
||
@endcode
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
@note
|
||
Floating point multiplication is communicative (`a * b = b * a`) but is not
|
||
@b necessarily associative. i.e. `(a * b) * c` is not necessarily equal to
|
||
`a * (b * c)`.
|
||
|
||
@anchor axbinbitwiseop
|
||
@par Bitwise operands
|
||
Binary bitwise operations have the following forms:
|
||
@par
|
||
<table>
|
||
<tr><td bgcolor="#ffc4c4"> @a `lhs` @b `&` @a `rhs` </td></tr>
|
||
<tr><td bgcolor="#ffc4c4"> @a `lhs` <b> `|` </b> @a `rhs` </td></tr>
|
||
<tr><td bgcolor="#ffc4c4"> @a `lhs` @b `^` @a `rhs` </td></tr>
|
||
<tr><td bgcolor="#ffc4c4"> @a `lhs` @b `<<` @a `rhs` </td></tr>
|
||
<tr><td bgcolor="#ffc4c4"> @a `lhs` @b `>>` @a `rhs` </td></tr>
|
||
</table>
|
||
@par
|
||
These operations only run on @b integral operands. After @ref axtypeprecedence
|
||
"implicit conversion", the result of the binary operation:
|
||
- with the @b `&` (@ref axtokens "ampersand token") is the result of the
|
||
logical AND operation on each pair of the corresponding bits of the input
|
||
operands.
|
||
- with the <b> `|` </b> (@ref axtokens "pipe token") is the result of the
|
||
logical OR operation on each pair of the corresponding bits of the input
|
||
operands.
|
||
- with the @b `^` (@ref axtokens "hat token") is the result of the
|
||
logical XOR operation on each pair of the corresponding bits of the input
|
||
operands.
|
||
- with the @b `<<` (@ref axtokens "less than tokens") is the value shifted left
|
||
with zeros shifted in on the right.
|
||
- with the @b `>>` (@ref axtokens "greater than tokens") is the value shifted
|
||
right with zeros shifted in on the left.
|
||
@par
|
||
<table>
|
||
<tr style="text-align:center">
|
||
<th>Left Operand Type</th><th>Binary Op(s)</th><th>Right Operand Type</th><th>Description</th>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td>@ref axscalars "intergral"</td>
|
||
<td>`& | ^ << >>`</td>
|
||
<td>@ref axscalars "intergral"</td>
|
||
<td style="text-align:left">
|
||
Returns the result of the bitwise operation as described above. If either operand
|
||
is not an integral type (`bool` `int32` or `int64`), the program is ill formed.
|
||
</td>
|
||
</table>
|
||
|
||
|
||
@subsubsection axopcomparison Comparisons / Relational
|
||
@par
|
||
Binary comparison and relational operations compute the result of a equality
|
||
operand token on two inputs and returns the result. The inputs are not modified,
|
||
however may be copied and @ref axtypeprecedence "implicitly cast" to temporary
|
||
values if the types do not match. The result type of all comparison operators
|
||
is of type @b `bool`. Binary comparison operations have the following forms:
|
||
@par
|
||
<table>
|
||
<tr><th>Operator Name</th><th>Operator Syntax</th><th>Returns</th></tr>
|
||
<tr><td>Equal to</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`==`</b> @a `rhs` </td>
|
||
<td>Returns `true` if both operands are equal</td></tr>
|
||
<tr><td>Not equal to</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`!=`</b> @a `rhs` </td>
|
||
<td>Returns `true` if operands are not equal</td></tr>
|
||
<tr><td>Less than</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`<`</b> @a `rhs` </td>
|
||
<td>Returns `true` the left hand side value is less than the right hand side</td></tr>
|
||
<tr><td>Greater than</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`>`</b> @a `rhs` </td>
|
||
<td>Returns `true` the left hand side value is greater than the right hand side</td></tr>
|
||
<tr><td>Less than or equal to</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`<=`</b> @a `rhs` </td>
|
||
<td>Returns `true` the left hand side value is less than or equal to the right hand side</td></tr>
|
||
<tr><td>Greater than or equal to</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`>=`</b> @a `rhs` </td>
|
||
<td>Returns `true` the left hand side value is greater than or equal to the right hand side</td></tr>
|
||
</table>
|
||
@par
|
||
The following combination of AX type categories are supported for comparison
|
||
operations (if an operation is not listed, it is not supported):
|
||
@par
|
||
<table>
|
||
<tr style="text-align:center">
|
||
<th>Left Operand Type</th><th>Binary Op(s)</th><th>Right Operand Type</th><th>Description</th>
|
||
</tr>
|
||
<tr style="text-align:center"><td rowspan="3">@ref axscalars "scalar"</td><td rowspan="1">`== != < > <= >=`</td><td>@ref axscalars "scalar"</td>
|
||
<td style="text-align:left">Returns the result of the scalar comparison.</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td rowspan="2">`== !=`</td>
|
||
<td>@ref axvecmats "vector"</td>
|
||
<td style="text-align:left" rowspan="2">
|
||
Performs per component comparisons (after
|
||
@ref axtypeprecedence "implicit conversion") with the lefthand side scalar to
|
||
every element of the right hand side vector or matrix and perform a logical AND
|
||
combination on the results of these comparisons. This effectively returns true
|
||
if every element of the vector or matrix is equal to the scalar.
|
||
<!-- A -->@code{.c}
|
||
vec3f a = 2.0f;
|
||
int b = 1;
|
||
bool c = b == a;
|
||
@endcode
|
||
is equal to:
|
||
<!-- A -->@code{.c}
|
||
vec3f a = 2.0f;
|
||
int b = 1;
|
||
bool c = a[0] == b;
|
||
for (int i = 1; i < 3; ++i) c &= a[i] == b;
|
||
@endcode
|
||
</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td>@ref axvecmats "matrix"</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td style="border-top-width: thick" rowspan="2">@ref axvecmats "vector"</td>
|
||
<td style="border-top-width: thick; text-align:center" rowspan="1">`== != < > <= >=`</td>
|
||
<td style="border-top-width: thick">@ref axscalars "scalar"</td>
|
||
<td style="border-top-width: thick;text-align:left">Same as `scalar op vector`</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td rowspan="1">`== !=`</td>
|
||
<td>@ref axvecmats "vector"</td>
|
||
<td style="text-align:left">
|
||
Performs binary comparison operations (after
|
||
@ref axtypeprecedence "implicit conversion") on each pair corresponding
|
||
components in the vector operands and returns true if all component pairs are
|
||
equal. <b>Operand sizes must match.</b>
|
||
<!-- A -->@code{.c}
|
||
vec3f a = 1, b = 2;
|
||
bool c = a == b;
|
||
@endcode
|
||
is equal to:
|
||
<!-- A -->@code{.c}
|
||
vec3f a = 1, b = 2;
|
||
bool c = a[0] == b[0];
|
||
for (int i = 1; i < 3; ++i) c &= a[i] == b[i];
|
||
@endcode
|
||
</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td style="border-top-width: thick" rowspan="2">@ref axvecmats "matrix"</td>
|
||
<td style="border-top-width: thick; text-align:center" rowspan="1">`== != < > <= >=`</td>
|
||
<td style="border-top-width: thick">@ref axscalars "scalar"</td>
|
||
<td style="border-top-width: thick;text-align:left">Same as `scalar op matrix`</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td rowspan="1">`== !=`</td>
|
||
<td>@ref axvecmats "matrix"</td>
|
||
<td style="text-align:left">
|
||
Performs binary comparison operations (after
|
||
@ref axtypeprecedence "implicit conversion") on each pair corresponding
|
||
components in the matrix operands and returns true if all component pairs are
|
||
equal. <b>Operand sizes must match.</b>
|
||
<!-- A -->@code{.c}
|
||
mat4f a = 1, b = 2;
|
||
bool c = a == b;
|
||
@endcode
|
||
is equal to:
|
||
<!-- A -->@code{.c}
|
||
mat4f a = 1, b = 2;
|
||
bool c = a[0] == b[0];
|
||
for (int i = 1; i < 16; ++i) c &= a[i] == b[i];
|
||
@endcode
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
|
||
|
||
@subsubsection axopbinlogical Logical
|
||
@par
|
||
Binary logical operations compute and return the result of a boolean operation
|
||
on two operands. Both operands are implicitly converted to @b `bool` types if
|
||
they are not already.
|
||
@warning
|
||
These operators are short-circuiting; for logical AND, the second operand is
|
||
only evaluated if the first is @b true. For logical OR, the second operand is
|
||
only evaluated if the first is @b false. In both cases, the first operand is
|
||
always evaluated.
|
||
@par
|
||
They have the following forms:
|
||
@par
|
||
<table>
|
||
<tr><th>Operator Name</th><th>Operator Syntax</th><th>Returns</th></tr>
|
||
<tr><td>AND</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`&&`</b> @a `rhs` </td>
|
||
<td>Returns true if both operands are true. Otherwise, the result is false. This
|
||
operator is short-circuiting.</td></tr>
|
||
<tr><td>Inclusive OR</td><td bgcolor="#ffc4c4"> @a `lhs` <b>`||`</b> @a `rhs` </td>
|
||
<td>Returns true if either the first or the second operand is true. This operator
|
||
is short-circuiting.</td></tr>
|
||
</table>
|
||
@par
|
||
The following combination of AX type categories are supported for comparison
|
||
operations (if an operation is not listed, it is not supported):
|
||
@par
|
||
<table>
|
||
<tr style="text-align:center">
|
||
<th>Left Operand Type</th><th>Binary Op(s)</th><th>Right Operand Type</th><th>Description</th>
|
||
</tr>
|
||
<tr style="text-align:center"><td>@ref axscalars "scalar"</td><td>`&& ||`</td><td>@ref axscalars "scalar"</td>
|
||
<td style="text-align:left">Returns the result of the scalar logical operation.
|
||
Both scalars are converted to bools if they are not already.</td>
|
||
</tr>
|
||
</table>
|
||
|
||
|
||
@subsection axopunary Unary Operators
|
||
@par
|
||
Unary operators only execute on a single value. The operator token(s) may come
|
||
before or after the value, precedence of which is defined by AX's
|
||
@ref axopprecedence "operator precedence". Arithmetic, logical and
|
||
increment / decrement operators are supported.
|
||
|
||
|
||
@subsubsection axopunarithmetic Arithmetic
|
||
@par
|
||
Arithmetic unary operators are comprised of arithemtic and bitwise operators.
|
||
@par
|
||
<table>
|
||
<tr><th>Operator Name</th><th>Operator Syntax</th><th>Returns</th></tr>
|
||
<tr><td>Unary plus</td><td bgcolor="#ffc4c4"> <b>`+`</b>@a `a` </td>
|
||
<td>Returns the value of its operand, @b `a`</td>
|
||
</tr>
|
||
<tr><td>Unary minus</td><td bgcolor="#ffc4c4"> <b>`-`</b>@a `a` </td>
|
||
<td>Returns the negative representation of @b `a`</td>
|
||
</tr>
|
||
<tr><td>Bitwise NOT</td><td bgcolor="#ffc4c4"> <b>`~`</b>@a `a` </td>
|
||
<td>Returns the bitwise NOT (one's complement) value of @b `a`. This operator
|
||
is only valid on integral element types.</td>
|
||
</tr>
|
||
</table>
|
||
@par
|
||
The following combination of AX type categories are supported for unary
|
||
arithmetic operations (if an operation is not listed, it is not supported):
|
||
@par
|
||
<table>
|
||
<tr style="text-align:center">
|
||
<th>Operand Type</th><th>Binary Op(s)</th><th>Description</th>
|
||
</tr>
|
||
<tr style="text-align:center"><td>@ref axscalars "scalar"</td><td rowspan="2">`+ - ~`</td>
|
||
<td style="text-align:left">Returns the result of the scalar unary operations.</td>
|
||
</tr>
|
||
<tr style="text-align:center"><td>@ref axvecmats "vector"</td>
|
||
<td style="text-align:left">
|
||
Performs per component unary operations, returning a new vector with each
|
||
element holding the corresponding result. <b>Operand sizes must match.</b>
|
||
<!-- A -->@code{.c}
|
||
vec3f a = 2;
|
||
vec3f b = -a;
|
||
@endcode
|
||
is equal to:
|
||
<!-- A -->@code{.c}
|
||
vec3f a = 2;
|
||
vec3f b;
|
||
for (int i = 0; i < 3; ++i) b[i] = -a[i];
|
||
@endcode
|
||
@b Note: The bitwise not `~` operator is only valid on integer vector types;
|
||
`vec2i`, `vec3i` and `vec4i`.
|
||
</td>
|
||
</tr>
|
||
<tr style="text-align:center"><td>@ref axvecmats "matrix"</td><td>`+ -`</td>
|
||
<td style="text-align:left">
|
||
Performs per component unary operations, returning a new matrix with each
|
||
element holding the corresponding result. <b>Operand sizes must match.</b>
|
||
<!-- A -->@code{.c}
|
||
vec3f a = 2;
|
||
vec3f b = -a;
|
||
@endcode
|
||
is equal to:
|
||
<!-- A -->@code{.c}
|
||
vec3f a = 2;
|
||
vec3f b;
|
||
for (int i = 0; i < 3; ++i) b[i] = -a[i];
|
||
@endcode
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
|
||
|
||
@subsubsection axopunlogical Logical
|
||
@par
|
||
Logical unary operators consist of a single operand.
|
||
@par
|
||
<table>
|
||
<tr><th>Operator Name</th><th>Operator Syntax</th><th>Returns</th></tr>
|
||
<tr><td>Logical NOT</td><td bgcolor="#ffc4c4"> <b>`!`</b>@a `a` </td>
|
||
<td>Returns true if the operand is false. Otherwise, returns false.</td>
|
||
</tr>
|
||
</table>
|
||
@par
|
||
The following combination of AX type categories are supported for logical unary
|
||
operations (if an operation is not listed, it is not supported):
|
||
@par
|
||
<table>
|
||
<tr style="text-align:center">
|
||
<th>Operand Type</th><th>Binary Op(s)</th><th>Description</th>
|
||
</tr>
|
||
<tr style="text-align:center"><td>@ref axscalars "scalar"</td><td rowspan="2">`!`</td>
|
||
<td style="text-align:left">Returns the result of the scalar logical operation.
|
||
The scalar operand is converted to a bool if it is not already.</td>
|
||
</tr>
|
||
<tr style="text-align:center"><td>@ref axvecmats "vector"</td>
|
||
<td style="text-align:left">
|
||
Performs per component unary operations, returning a new vector with each
|
||
element holding the corresponding result. <b>Operand sizes must match.</b>
|
||
<!-- A -->@code{.c}
|
||
vec3i a = 2;
|
||
vec3i b = !a;
|
||
@endcode
|
||
is equal to:
|
||
<!-- A -->@code{.c}
|
||
vec3i a = 2;
|
||
vec3i b;
|
||
for (int i = 0; i < 3; ++i) b[i] = !a[i];
|
||
@endcode
|
||
@b Note: The logical not `!` operator is only valid on integer vector types;
|
||
`vec2i`, `vec3i` and `vec4i`.
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
|
||
|
||
@subsubsection axopunincdec Increment / Decrement
|
||
@par
|
||
Increment/decrement operators increment or decrement the value of a scalar, or
|
||
each component of a vector or matrix. They have the following forms:
|
||
@par
|
||
<table>
|
||
<tr><th>Operator Name</th><th>Operator Syntax</th><th>Returns</th></tr>
|
||
<tr><td>Pre-increment</td><td bgcolor="#ffc4c4"> <b>`++`</b>@a `a` </td><td>Returns a reference to the incremented result.</td>
|
||
<tr><td>Post-increment</td><td bgcolor="#ffc4c4">@a `a`<b>`++`</b> </td><td>Returns a copy of the incremented result.</td>
|
||
<tr><td>Pre-decrement</td><td bgcolor="#ffc4c4"> <b>`--`</b>@a `a` </td><td>Returns a reference to the decremented result.</td>
|
||
<tr><td>Post-decrement</td><td bgcolor="#ffc4c4"> @a `a`<b>`--`</b> </td><td>Returns a copy of the decremented result.</td>
|
||
</tr>
|
||
</table>
|
||
@par
|
||
Importantly, pre evaluation returns a reference to the value operand, where as
|
||
post evaluation returns a copy of the operand. The following combination of AX
|
||
type categories are supported for logical unary operations (if an operation is
|
||
not listed, it is not supported):
|
||
@par
|
||
<table>
|
||
<tr style="text-align:center">
|
||
<th>Operand Type</th><th>Binary Op(s)</th><th>Description</th>
|
||
</tr>
|
||
<tr style="text-align:center"><td>@ref axscalars "scalar"</td>
|
||
<td>`++(pre) (post)++` <br/> `--(pre) (post)--`</td>
|
||
<td style="text-align:left">Returns the result (reference or copy) of the scalar
|
||
increment or decrement operation.\n
|
||
@b Note: boolean incrementation and decrementation is not supported. Only
|
||
`int32`, `int64`, `float` and `double` types are valid. </td>
|
||
</tr>
|
||
</table>
|
||
|
||
|
||
@subsection axopaccess Container Access
|
||
@par
|
||
Container access operators are valid on AX Vector and matrix types. They have
|
||
the following forms:
|
||
@par
|
||
<table>
|
||
<tr><th>Operator Name</th><th>Operator Syntax</th><th>Returns</th></tr>
|
||
<tr style="text-align:left">
|
||
<td>Dot Component Access</td>
|
||
<td bgcolor="#ffc4c4"> <em>`vector`</em> <b>.</b> @a `component` </td>
|
||
<td>Reference to component @a `component` of @a `vector`</td>
|
||
</tr>
|
||
<tr style="text-align:left">
|
||
<td>Container Component Access</td>
|
||
<td bgcolor="#ffc4c4"> <em>`container`</em> <b>[</b> @a `exp` <b>]</b> </td>
|
||
<td>Reference to component at index @a `exp` of @a `container`</td>
|
||
</tr>
|
||
<tr style="text-align:left">
|
||
<td>Matrix Component Access</td>
|
||
<td bgcolor="#ffc4c4"> <em>`matrix`</em> <b>[</b> @a `exp1`, <em>`exp2`</em> <b>]</b> </td>
|
||
<td>Reference to component in row <b><em>`exp1`</em></b>, column <b><em>`exp2`</em></b>.
|
||
Also equal to returning a reference to component at index: <b><em> `[exp1 * dimension + exp2]` </em></b>
|
||
of @a `matrix` where @a `dimension` is the the size of the matrix</td>
|
||
</tr>
|
||
</table>
|
||
@par
|
||
As data is stored contiguously for both vectors and matrices, the <b>`[]`</b>
|
||
operator is valid for both types. However the <b>.</b> operator is only valid
|
||
on vector types, and the <b>`[,]`</b> operator is only valid on matrix types.
|
||
As return values for these operators are references, any modifications through
|
||
@ref axopassignment "assignments" will update the stored value in the
|
||
container.
|
||
@par . operator
|
||
The dot operator <b>.</b> is only valid for vector types. It has the form:
|
||
@par
|
||
<table><tr>
|
||
<td bgcolor="#ffc4c4"> @a `vector` <b>.</b> @a `component` </td>
|
||
</tr></table>
|
||
@par
|
||
Where component is one of the below supported component letters. It only provides
|
||
access for the first three elements of any vector (for @b `vec2` types, only the
|
||
first 2 components are accessible). Accessing a vector using the dot operator is
|
||
fundamentally the same as using the <b>`[]`</b> operator with the corresponding
|
||
integer index.
|
||
@par
|
||
<!-- A -->@code{.c}
|
||
vec4i a = { 6, 7, 8, 9 };
|
||
int b = a.z; // get the the third elements value (8)
|
||
@endcode
|
||
<center>
|
||
@f[
|
||
A=\begin{bmatrix}
|
||
a_{0}\quad a_{1}\quad a_{2}
|
||
\end{bmatrix}
|
||
@f]
|
||
| Component | Access Index | Result |
|
||
|:-----------:|:--------------:|:-------------:|
|
||
| @b `A.x` | 0 | @f$ a_{0} @f$ |
|
||
| @b `A.r` | 0 | @f$ a_{0} @f$ |
|
||
| @b `A.y` | 1 | @f$ a_{1} @f$ |
|
||
| @b `A.g` | 1 | @f$ a_{1} @f$ |
|
||
| @b `A.z` | 2 | @f$ a_{2} @f$ |
|
||
| @b `A.b` | 2 | @f$ a_{2} @f$ |
|
||
</center>
|
||
@par
|
||
This operator can provide more immediately readability when working with
|
||
expressions that focus on colour or Cartesian coordinate systems.
|
||
@anchor axvecaccessop
|
||
@par [] operator
|
||
The <b>`[]`</b> operator is valid for both vectors and matrices. It has the form:
|
||
@par
|
||
<table><tr>
|
||
<td bgcolor="#ffc4c4"> @a `container` <b>[</b><em>`exp`</em><b>]</b> </td>
|
||
</tr></table>
|
||
@par
|
||
@a `exp` is expected to evaluate to a value which is castable to an integer
|
||
following the @ref axopassignment "assignment casting" rules and falls within
|
||
the valid size of the @a `container`. <b>No bounds checking is performed</b>.
|
||
@par
|
||
As matrices are also an array of contigous values, they can be accessed in the
|
||
same way. This can make some operations much simplier; a typical example being
|
||
iterating through all matrix elements and performing some logic:
|
||
@par
|
||
@code{.c}
|
||
vec3f a = 0;
|
||
a[0] = 1; // valid
|
||
a[""] = 1; // invalid - can't cast to int
|
||
a[1.2f] = 1; // valid - float exp will be clamped to an int
|
||
a[a[0]] = 1; // valid - use the value of a[0] to index into a
|
||
// assign each element its actual index value i.e. b[5] = 5;
|
||
mat4d b;
|
||
for (int i = 0; i < 16; ++i) b[i] = i;
|
||
@endcode
|
||
@anchor axmataccessop
|
||
@par [,] operator
|
||
The <b>`[,]`</b> operator is only valid for matrices. It has the form:
|
||
@par
|
||
<table><tr>
|
||
<td bgcolor="#ffc4c4"> @a `matrix` <b>[</b><em>`exp1`</em>, <em>`exp2`</em><b>]</b> </td>
|
||
</tr></table>
|
||
@par
|
||
@a `exp1` and @a `exp2` are expected to evaluate to a value which is castable to
|
||
an integer following the @ref axopassignment "assignment casting" rules and
|
||
falls within the valid size of the @a `matrix` dimensions. <b>No bounds checking
|
||
is performed</b>. In general it is more readable to use this operator when
|
||
accessing specific elements, where @b `exp1` is the row index and @b `exp2` is
|
||
the column index. The tables below show the different access patterns for
|
||
@b `3x3` and @b `4x4` matrices.
|
||
@par
|
||
<!-- A -->@code{.c}
|
||
mat3f a;
|
||
for (int i = 0; i < 3; ++i)
|
||
for (int j = 0; j < 3; ++j)
|
||
a[i,j] = i*j; // assign matrix element the product of its index
|
||
@endcode
|
||
@par
|
||
<table>
|
||
<tr style="text-align:center">
|
||
<td style="border:none" colspan=3>
|
||
@f[
|
||
A=\begin{bmatrix}
|
||
a_{00}\quad a_{01}\quad a_{02}\\
|
||
a_{10}\quad a_{11}\quad a_{12}\\
|
||
a_{20}\quad a_{21}\quad a_{22}\\
|
||
\end{bmatrix}
|
||
@f]
|
||
</td>
|
||
<td style="border:none"></td>
|
||
<td style="border:none" colspan=3>
|
||
@f[
|
||
A=\begin{bmatrix}
|
||
a_{00}\quad a_{01}\quad a_{02}\quad a_{03}\\
|
||
a_{10}\quad a_{11}\quad a_{12}\quad a_{13}\\
|
||
a_{20}\quad a_{21}\quad a_{22}\quad a_{23}\\
|
||
a_{30}\quad a_{31}\quad a_{32}\quad a_{33}\\
|
||
\end{bmatrix}
|
||
@f]
|
||
</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<th>Access [a]</th>
|
||
<th>Access [a,b]</th>
|
||
<th style="border-right-style:none;">Result</th>
|
||
<td style="border:none" rowspan="17"></td> <!-- table seperator -->
|
||
<th>Access [a]</th>
|
||
<th>Access [a,b]</th>
|
||
<th>Result</th>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td><code>A[0]</code></td>
|
||
<td><code>A[0,0]</code></td>
|
||
<td>@f$ a_{00} @f$</td>
|
||
<td><code>A[0]</code></td>
|
||
<td><code>A[0,0]</code></td>
|
||
<td>@f$ a_{00} @f$</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td><code>A[1]</code></td>
|
||
<td><code>A[0,1]</code></td>
|
||
<td>@f$ a_{01} @f$</td>
|
||
<td><code>A[1]</code></td>
|
||
<td><code>A[0,1]</code></td>
|
||
<td>@f$ a_{01} @f$</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td><code>A[2]</code></td>
|
||
<td><code>A[0,2]</code></td>
|
||
<td>@f$ a_{02} @f$</td>
|
||
<td><code>A[2]</code></td>
|
||
<td><code>A[0,2]</code></td>
|
||
<td>@f$ a_{02} @f$</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td><code>A[3]</code></td>
|
||
<td><code>A[1,0]</code></td>
|
||
<td>@f$ a_{10} @f$</td>
|
||
<td><code>A[3]</code></td>
|
||
<td><code>A[0,3]</code></td>
|
||
<td>@f$ a_{03} @f$</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td><code>A[4]</code></td>
|
||
<td><code>A[1,1]</code></td>
|
||
<td>@f$ a_{10} @f$</td>
|
||
<td><code>A[4]</code></td>
|
||
<td><code>A[1,0]</code></td>
|
||
<td>@f$ a_{10} @f$</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td><code>A[5]</code></td>
|
||
<td><code>A[1,2]</code></td>
|
||
<td>@f$ a_{12} @f$</td>
|
||
<td><code>A[5]</code></td>
|
||
<td><code>A[1,1]</code></td>
|
||
<td>@f$ a_{11} @f$</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td><code>A[6]</code></td>
|
||
<td><code>A[2,0]</code></td>
|
||
<td>@f$ a_{20} @f$</td>
|
||
<td><code>A[6]</code></td>
|
||
<td><code>A[1,2]</code></td>
|
||
<td>@f$ a_{12} @f$</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td><code>A[7]</code></td>
|
||
<td><code>A[2,1]</code></td>
|
||
<td>@f$ a_{21} @f$</td>
|
||
<td><code>A[7]</code></td>
|
||
<td><code>A[1,3]</code></td>
|
||
<td>@f$ a_{13} @f$</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td><code>A[8]</code></td>
|
||
<td><code>A[2,2]</code></td>
|
||
<td>@f$ a_{22} @f$</td>
|
||
<td><code>A[8]</code></td>
|
||
<td><code>A[2,0]</code></td>
|
||
<td>@f$ a_{20} @f$</td>
|
||
</tr> <!-- ******************** MAT4 DATA ONLY ******************** -->
|
||
<tr style="text-align:center">
|
||
<td style="border:none;" colspan="3" rowspan="7"></td>
|
||
<td><code>A[9]</code></td>
|
||
<td><code>A[2,1]</code></td>
|
||
<td>@f$ a_{21} @f$</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td><code>A[10]</code></td>
|
||
<td><code>A[2,2]</code></td>
|
||
<td>@f$ a_{22} @f$</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td><code>A[11]</code></td>
|
||
<td><code>A[2,3]</code></td>
|
||
<td>@f$ a_{23} @f$</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td><code>A[12]</code></td>
|
||
<td><code>A[3,0]</code></td>
|
||
<td>@f$ a_{30} @f$</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td><code>A[13]</code></td>
|
||
<td><code>A[3,1]</code></td>
|
||
<td>@f$ a_{31} @f$</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td><code>A[14]</code></td>
|
||
<td><code>A[3,2]</code></td>
|
||
<td>@f$ a_{32} @f$</td>
|
||
</tr>
|
||
<tr style="text-align:center">
|
||
<td><code>A[15]</code></td>
|
||
<td><code>A[3,3]</code></td>
|
||
<td>@f$ a_{33} @f$</td>
|
||
</tr>
|
||
</table>
|
||
|
||
|
||
@subsection axopother Other
|
||
@par
|
||
A number of uncategorised operators that are more general are documented in this
|
||
section. They have the following forms:
|
||
@par
|
||
<table>
|
||
<tr><th>Operator Name</th><th>Operator Syntax</th><th>Returns</th></tr>
|
||
<tr style="text-align:left">
|
||
<td>Call / Explicit Cast</td>
|
||
<td bgcolor="#ffc4c4"> <em>`a`</em><b>`(...)`</b></td>
|
||
<td>Returns the result of a function call or inbuilt explicit cast</td>
|
||
</tr>
|
||
<tr style="text-align:left">
|
||
<td>Comma</td>
|
||
<td bgcolor="#ffc4c4"> <em>`a`</em><b>,</b> <em>`b`</em></td>
|
||
<td>Returns the value of @b `b` after chained evaluation</td>
|
||
</tr>
|
||
<tr style="text-align:left">
|
||
<td>Ternary Conditional</td>
|
||
<td bgcolor="#ffc4c4"> <em>`a`</em> <b>`?`</b> <em>`b`</em> <b>`:`</b><em>`c`</em></td>
|
||
<td>@b `b` if @b `a` is @b true, @b `c` otherwise.</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Vector/Matrix Initializer</td>
|
||
<td bgcolor="#ffc4c4"> <b>`{`</b> <em> `a, `</em> `b `<b>`... }`</b> </td>
|
||
<td>Returns a temporary vector or matrix</td>
|
||
</tr>
|
||
</table>
|
||
|
||
@par Call / Explicit Cast
|
||
The function call operator provides the ability to invoke functions @b or invoke
|
||
a supported explicit cast. It has the form:
|
||
@par
|
||
<table><tr>
|
||
<td bgcolor="#ffc4c4"> <em> `func(a, b, c, ...)` </em></td>
|
||
</tr></table>
|
||
@par
|
||
Where @b `func` is a function name @b or a valid explicit cast typename. Explicit
|
||
casts are only supported for @ref axscalars "scalar types". For example:
|
||
<!-- A -->@code{.c}
|
||
int a = int(1.1f);
|
||
vec3f b = 1.0f;
|
||
a = int(b.x);
|
||
@endcode
|
||
@par
|
||
Whilst explicit casts take only a single argument, the operator itself supports
|
||
multiple or empty arguments for function calls. Whe multiple arguments are
|
||
provided, they are parsed from first to last and processed in reverse order.
|
||
@b However, the order of runtime evaluation is @b unspecified i.e. they may
|
||
evaluate in any order. Each function parameter is initialized with its
|
||
corresponding argument after following implicit conversion of assignments where
|
||
necessary.
|
||
@par
|
||
See the @ref axfunctions "function documentation" for more information on
|
||
functions.
|
||
@par Comma
|
||
The Comma operator has the form:
|
||
@par
|
||
<table><tr>
|
||
<td bgcolor="#ffc4c4"><em>`a`</em><b>`,` </b><em>`b`</em></td>
|
||
</tr></table>
|
||
@par
|
||
Where @b `a` and @b `b` are expressions. Chained expressions evaluate each
|
||
expression in syntactical order (first to last), discarding any return value
|
||
except for the last expression, which is returned from the entire list. Note that
|
||
although return values for any expression but the last are discarded, their side
|
||
effects are still applied before subsequent expression are evaluated. For
|
||
example:
|
||
<!-- A -->@code{.c}
|
||
int a = 5;
|
||
a-=1, a+=2; // a = 6
|
||
a = a--, ++a; // exp1: a = a--, exp2: ++a. a = 7
|
||
@endcode
|
||
@note
|
||
Although you may consider the comma operator as a type of binary operator, it
|
||
is fundamentally different as the types either side of the operator do @b not
|
||
interact. Each expression in the comma operator is evaluated independently of
|
||
all other expressions.
|
||
|
||
@anchor axopternary
|
||
@par Ternary Conditional
|
||
The ternary conditional operator can be thought of as an in-line @ref axbranching
|
||
"if-else statement" that returns a value, where each of the if/else branches has
|
||
a single expression that will be returned. It has the form:
|
||
@par
|
||
<table><tr>
|
||
<td bgcolor="#ffc4c4"><em>`a`</em> <b>`?`</b> <em>`b`</em> <b>`:`</b><em>`c`</em></td>
|
||
</tr></table>
|
||
Where @b `a` is the condition, evaluated and converted to @b bool, and @b `b` and @b
|
||
`c` are expressions of the same or implicit-castable types. @b `b` is evaluated and
|
||
returned if the condition is @b true, @b `c` is evaluated and returned if the
|
||
condition is @b false. Only the expression out of @b `b` and @b `c` that is
|
||
returned will be evaluated. Expressions with no return value (a.k.a @b `void`)
|
||
are supported as long as @b `b` and @b `c` are both of this type.
|
||
@par
|
||
Also supported is the 'Elvis' operator, <b>`a` `?` `:` `c`</b> (or `?:`).
|
||
Here, @b `a` is evaluated once, and if when converted to @b bool is @b true, @b `a` is
|
||
returned, otherwise @b `c` is evaluated and returned. In this case, @b `a` and @b
|
||
`c` must be the same or implicit-castable types, and both implicit-castable to @b bool.
|
||
|
||
@anchor axvecmatinit
|
||
@par Vector/Matrix Initializer
|
||
@ref axvecmats "Vectors and matrices" can be represented as local variables (e.g.
|
||
@b `vec3f`), external attributes or parameters (e.g. @b `vec3f\@attrib`) or as
|
||
temporary values using the vector/matrix initializer syntax. This operator has
|
||
the form:
|
||
@par
|
||
<table><tr>
|
||
<td bgcolor="#ffc4c4"> <b>`{`</b> <em>`a, b `</em><b>`... }`</b> </td>
|
||
</tr></table>
|
||
@par
|
||
Where @b `a` and @b `b` are expressions returning a scalar value. When this
|
||
operator is invoked with a specific number of arguments, a vector or matrix is
|
||
implicitly created with a copy of those arguments which can be assigned to an
|
||
existing container of matching size. Expression in the operator are evaluated
|
||
from first to last. This operator is only valid with argument lists of sizes
|
||
2, 3, 4, 9 and 16, which implicitly represent <b>vec2, vec3, vec4, mat3,</b> and
|
||
@b mat4 types respectively. For example:
|
||
<!-- A -->@code{.c}
|
||
vec3f a = { 1.0f, 2.0f, 3.0f }; // right hand side of assignment creates a vec3f
|
||
vec3f b = dot(a, { a[0], 5.0, 6.0 }); // second argument creates a vec3d
|
||
@endcode
|
||
@note
|
||
In the above examples, the value of <b>`a[0]`</b> is copied into the initializer
|
||
operator.
|
||
@par Initialization Type
|
||
A mixture of arbitrary scalar types can be used in the initializer operator e.g:
|
||
<!-- A -->@code{.c}
|
||
mat3f a = {
|
||
true, 0s, 0,
|
||
0l, 0.0f, 0.0,
|
||
false, 1, 2
|
||
};
|
||
@endcode
|
||
@par
|
||
The temporary container evaluates all expressions and uses the @b highest ranking
|
||
type (as defined by @ref axtypeprecedence "arithmetic type precedence") to infer
|
||
the element type of the container, implicitly casting all other types to that
|
||
type where necessary. In the above example, the temporary created forms a
|
||
@b `mat3d`, before being implicitly cast to a @b `mat3f` due to the assignment.
|
||
|
||
|
||
@subsection axopprecedence Operator Precedence
|
||
@par
|
||
The below table shows the precedence and associativity of all AX operators.
|
||
Operators are listed in descending precedence.
|
||
@par
|
||
<table>
|
||
<tr>
|
||
<th style="text-align: left">Precedence</th>
|
||
<th style="text-align: left">Operator</th>
|
||
<th style="text-align: left">Description</th>
|
||
<th style="text-align: left">Associativity</th>
|
||
</tr>
|
||
<tr> <!-- *********************** ROW 1 *********************** -->
|
||
<th>1</th>
|
||
<td> <code>()</code> </td>
|
||
<td> Parenthesis </td>
|
||
<td style="vertical-align: top" rowspan="5"> Left-to-right</td>
|
||
</tr>
|
||
<tr> <!-- *********************** ROW 2 *********************** -->
|
||
<th rowspan="4">2</th>
|
||
<td style="border-bottom-style: none"> <code>a++</code> <code>a\-\-</code></td>
|
||
<td style="border-bottom-style: none"> Suffix/postfix @ref axopunincdec </td>
|
||
</tr>
|
||
<tr>
|
||
<td style="border-bottom-style: none; border-top-style: none"> <code><i>type</i>()</code></td>
|
||
<td style="border-bottom-style: none; border-top-style: none"> @ref axopother "Functional cast"</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="border-bottom-style: none; border-top-style: none"> <code>a()</code></td>
|
||
<td style="border-bottom-style: none; border-top-style: none"> @ref axopother "Function call"</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="border-bottom-style: none; border-top-style: none"> <code>a[]</code> <code>.</code></td>
|
||
<td style="border-bottom-style: none; border-top-style: none"> @ref axopaccess </td>
|
||
</tr>
|
||
<tr> <!-- *********************** ROW 3 *********************** -->
|
||
<th rowspan="3">3</th>
|
||
<td style="border-bottom-style: none"> <code>++a</code> <code>\-\-a</code></td>
|
||
<td style="border-bottom-style: none"> Prefix @ref axopunincdec </td>
|
||
<td style="vertical-align: top" rowspan="3"> Right-to-left</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="border-bottom-style: none; border-top-style: none"> <code>+a</code> <code>-a</code></td>
|
||
<td style="border-bottom-style: none; border-top-style: none"> Unary @ref axopbinarithmetic "plus and minus"</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="border-bottom-style: none; border-top-style: none"> <code>!</code> <code>~</code></td>
|
||
<td style="border-bottom-style: none; border-top-style: none"> @ref axopbinlogical NOT and @ref axopunlogical NOT</td>
|
||
</tr>
|
||
<tr> <!-- *********************** ROW 4 *********************** -->
|
||
<th>4</th>
|
||
<td> <code>a*b</code> <code>a/b</code> <code>a%b</code></td>
|
||
<td> @ref axopbinarithmetic "Multiplication, division, and remainder" </td>
|
||
<td style="vertical-align: top" rowspan="11"> Left-to-right</td>
|
||
</tr>
|
||
<tr> <!-- *********************** ROW 5 *********************** -->
|
||
<th> 5</th>
|
||
<td> <code>a+b</code> <code>a−b</code></td>
|
||
<td> @ref axopbinarithmetic "Addition and subtraction" </td>
|
||
</tr>
|
||
<tr> <!-- *********************** ROW 6 *********************** -->
|
||
<th> 6</th>
|
||
<td> <code><<</code> <code>>></code></td>
|
||
<td> @ref axopbinarithmetic "Bitwise left shift and right shift" </td>
|
||
</tr>
|
||
<tr> <!-- *********************** ROW 7 *********************** -->
|
||
<th rowspan="2"> 7</th>
|
||
<td style="border-bottom-style: none"> <code><</code> <code><=</code></td>
|
||
<td style="border-bottom-style: none"> For @ref axopcomparison operators < and ≤ respectively</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="border-top-style: none"> <code>></code> <code>>=</code></td>
|
||
<td style="border-top-style: none"> For @ref axopcomparison operators > and ≥ respectively</td>
|
||
</tr>
|
||
<tr> <!-- *********************** ROW 8 *********************** -->
|
||
<th> 8</th>
|
||
<td> <code>==</code> <code>!=</code></td>
|
||
<td> For @ref axopcomparison operators = and ≠ respectively</td>
|
||
</tr>
|
||
<tr> <!-- *********************** ROW 9 *********************** -->
|
||
<th> 9</th>
|
||
<td> <code>&</code></td>
|
||
<td> @ref axopbinarithmetic AND</td>
|
||
</tr>
|
||
<tr> <!-- *********************** ROW 10 *********************** -->
|
||
<th> 10</th>
|
||
<td> <code>^</code></td>
|
||
<td> @ref axopbinarithmetic XOR (exclusive or)</td>
|
||
</tr>
|
||
<tr> <!-- *********************** ROW 11 *********************** -->
|
||
<th> 11</th>
|
||
<td> <code>|</code></td>
|
||
<td> @ref axopbinarithmetic OR (inclusive or)</td>
|
||
</tr>
|
||
<tr> <!-- *********************** ROW 12 *********************** -->
|
||
<th> 12</th>
|
||
<td> <code>&&</code></td>
|
||
<td> @ref axopbinlogical AND</a></td>
|
||
</tr>
|
||
<tr> <!-- *********************** ROW 13 *********************** -->
|
||
<th> 13</th>
|
||
<td> <code>||</code></td>
|
||
<td> @ref axopbinlogical OR</a></td>
|
||
</tr>
|
||
<tr> <!-- *********************** ROW 14 *********************** -->
|
||
<th rowspan="6"> 14</th>
|
||
<td style="border-bottom-style: none; border-top-style: none"> <code>a?b:c</code></td>
|
||
<td style="border-bottom-style: none; border-top-style: none"> @ref axopternary "Ternary operator" </td>
|
||
<td style="vertical-align: top" rowspan="6"> Right-to-left</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="border-bottom-style: none; border-top-style: none"> <code>=</code></td>
|
||
<td style="border-bottom-style: none; border-top-style: none"> @ref axopassignment "Direct assignment" </td>
|
||
</tr>
|
||
<tr>
|
||
<td style="border-bottom-style: none; border-top-style: none"> <code>+=</code> <code>-=</code></td>
|
||
<td style="border-bottom-style: none; border-top-style: none"> @ref axopassignment "Compound assignment" by sum and difference</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="border-bottom-style: none; border-top-style: none"> <code>*=</code> <code>/=</code> <code>%=</code></td>
|
||
<td style="border-bottom-style: none; border-top-style: none"> @ref axopassignment "Compound assignment" by product, quotient, and remainder</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="border-bottom-style: none; border-top-style: none"> <code><<=</code> <code>>>=</code></td>
|
||
<td style="border-bottom-style: none; border-top-style: none"> @ref axopassignment "Compound assignment" by bitwise left shift and right shift</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="border-top-style: none"> <code>&=</code> <code>^=</code> <code>|=</code></td>
|
||
<td style="border-top-style: none"> @ref axopassignment "Compound assignment" by bitwise AND, XOR, and OR</td>
|
||
</tr>
|
||
<tr> <!-- *********************** ROW 15 *********************** -->
|
||
<th> 15</th>
|
||
<td> <code>,</code></td>
|
||
<td> @ref axopother "Comma" </td>
|
||
<td> Left-to-right</td>
|
||
</tr></table>
|
||
@par
|
||
Note that associativity of unary operators is redundant (unary prefix operators
|
||
are always right-to-left and unary postfix operators are always left-to-right).
|
||
Operators that have the same precedence are bound to their arguments in the
|
||
direction of their associativity. For example, the expression <b>`a = b = c`</b> is
|
||
parsed as <b>`a = (b = c)`</b>, and not as <b>`(a = b) = c`</b> because of right-to-left
|
||
associativity of assignment, but <b>`a + b − c`</b> is parsed <b>`(a + b) − c`</b>
|
||
and not <b>`a + (b − c)`</b> because of left-to-right associativity of addition
|
||
and subtraction. @b Note that this is based off the <a href="https://en.cppreference.com/w/cpp/language/operator_precedence">C++ operator precedence</a>.
|
||
|
||
|
||
<br/><hr>
|
||
|
||
|
||
@section axtokens Tokens
|
||
@subsection axvaridentifiers Variable Identifiers
|
||
|
||
|
||
@subsection axliterals Literals
|
||
@par
|
||
Literals can be thought of as constant values that are known at compile time. e.g.
|
||
@code
|
||
i@a = 1; // the number 1 is a literal
|
||
@endcode
|
||
As AX supports different bit width scalar literals, it also supports suffix
|
||
literal tokens which, when using with a scalar literal, represent a literal of a
|
||
specific size. AX also supports implicit casting for all @ref axopassignment
|
||
"assignment" and @ref axopbinarithmetic "arithmetic" operations, so any literal
|
||
can be used to assign any scalar a value.
|
||
@par
|
||
<table>
|
||
<tr><th>Type</th><th>Literal Tokens</th></tr>
|
||
<tr><td>`bool`</td><td>Tokens @b `true` and @b `false`</td></tr>
|
||
<tr><td>`int32`</td><td>No suffix, automatically infered from integral literals</td></tr>
|
||
<tr><td>`int64`</td><td>The letter @b `l` e.g. @code int64 a = 10l; @endcode</td></tr>
|
||
<tr><td>`float`</td><td>The letter @b `f` e.g. @code float a = 0.0f; @endcode</td></tr>
|
||
<tr><td>`double`</td><td>No suffix, automatically infered from floating point literals.</td></tr>
|
||
<tr><td>`string`</td><td>Character strings wrapped in double quotes @b \" @b \"</td></tr>
|
||
</table>
|
||
@par
|
||
|
||
@subsection axcomments Comments
|
||
@subsection axkeywords Keywords
|
||
@subsection axreserved Reserved Keywords
|
||
|
||
<br/><hr>
|
||
|
||
@section axsyntax Syntax
|
||
|
||
|
||
@subsection axattribaccess Attribute Access
|
||
<!-- codecs not supported, how are points and volumes sampled (point vs volume) -->
|
||
|
||
<!--
|
||
Further, the active states of
|
||
OpenVDB voxels change which voxels AX will process. The defined behavior for all
|
||
cases is shown below.
|
||
@par
|
||
Consider a simple assignment example:
|
||
<!-- A -->@code{.c}
|
||
float@surface = float@density;
|
||
@endcode
|
||
@par
|
||
Assignment operations determine which volumes will be executed over. Here, the
|
||
AX program will only execute on the @b surface VDB whilst retaining access to
|
||
all available VDBs. There exists a number of possible states of both the
|
||
@b surface and @b density
|
||
volumes.
|
||
- Volumes have the same transform and the same topology
|
||
- Volumes have the same transform, but different topologies
|
||
- Volumes have different transforms, but the same topology
|
||
- Volumes have different transforms and different topologies
|
||
@par Matching Transforms
|
||
In the simplest case, all volumes processed have the same transform. Active
|
||
voxels in the @b surface VDB will receive a value sampled (@ref axattribaccess
|
||
"point sampled") at the corresponding @b index space position in the @b density
|
||
VDB. As the transforms match, this is guaranteed to be at the same @b world
|
||
space position. The topology of the @b density VDB does not influence which
|
||
values are assigned, AX simply queries the @b density VDB at the computed
|
||
position and uses whatever value is returned. This may be the VDB @b Background
|
||
value.
|
||
@par Different Transforms
|
||
When transforms differ, AX performs coordinate transformations from the source
|
||
VDB to the target VDB. Using some simple pseudo code, we can represent each
|
||
voxel's coordinate query:
|
||
@code{.unparsed}
|
||
foreach(ActiveVoxel in surface)
|
||
SurfaceIndexSpaceCoord = ActiveVoxel.indexSpaceCoordinate();
|
||
SurfaceWorldSpaceCoord = surface.transformToWorld(SurfaceIndexSpaceCoord);
|
||
DensityIndexSpaceCoord = density.transformToIndex(SurfaceWorldSpaceCoord);
|
||
ActiveVoxel = density.getValue(DensityIndexSpaceCoord);
|
||
@endcode
|
||
done()
|
||
-->
|
||
|
||
|
||
@subsection axexternalaccess External Parameter Access
|
||
@subsection axdecls Declarations
|
||
@subsection axscopes Scopes
|
||
@subsection axbranching Branching (if / else)
|
||
@subsection axloops Loops
|
||
|
||
|
||
<br/><hr>
|
||
|
||
|
||
@section axfunctions Functions
|
||
@par
|
||
For a list of all functions, see the @ref axfunctionlist "AX Function List".
|
||
@par
|
||
AX supports a variety of mathematical, string, utility and custom function calls
|
||
which can be used from within an AX program. Native function support is constantly
|
||
growing and we encourage users who wish to see particular methods exposed and
|
||
supported natively by AX to contact us. Whilst we can't guarantee
|
||
to accommodate every function, these requests provide the developers insights into
|
||
how the language is being used.
|
||
@par Function Execution Context
|
||
Some functions depend on the currently processing @ref axexecutionxcontext to
|
||
work correctly and will fail if called from an "invalid" context. Specifically,
|
||
there exists functions which operate on OpenVDB points or OpenVDB volume
|
||
grids and interact with the point or voxel data. Some of these methods are
|
||
incompatible for the other grid type (for example, @ref axdeletepoint
|
||
"deleting a point from a Point Data Grid") and will result in the compilation
|
||
failure of an AX program if an attempt is made it use them.
|
||
|
||
@subsection axuserfunctions User Functions
|
||
@par
|
||
User function declarations are not currently supported, but exist on the
|
||
AX Roadmap as a near future feature.
|
||
|
||
|
||
<br/><hr>
|
||
|
||
|
||
@section axvexsupport AX VEX Support
|
||
|
||
</div>
|
||
|
||
*/
|