Basics
dandy is an easy to integrate, single-header linear algebra vector library making use of expression templates for compile-time expression parsing – as such, operations can be performed on complex vector expressions without the need for intermediary vector allocations.
Vector types
-
template<class Scalar, size_t Size>
using vector = impl::value<Scalar, Size> - Param Scalar
The scalar type of the vector (e.g.
int
orfloat
)- Param Size
The size of the vector
-
namespace types
Typedefs
Note
Throughout this documentation, a “vector value” will refer to any of the types defined above
Construction
-
float3d v; // v contains 0, 0, 0
Is constructable from individual component values:
float3d v { 1.0, 2.0, 3.0 }; // v contains 1.0, 2.0, 3.0
Is explicitly constructable from a single value:
float3d v(1.0); // v contains 1.0, 1.0, 1.0
Is CopyConstructible and CopyAssignable:
float3d a { 1.0, 2.0, 3.0 }; float3d b = a; // b contains 1.0, 2.0, 3.0 float3d c; c = a; // c contains 1.0, 2.0, 3.0
Is constructable from a vector expression of the same size:
float3d a { 1.1, 2.2, 3.3 }; int3d b = a; // b contains 1, 2, 3 int3d c; c = a + b; // c contains 2, 4, 6 int2d d = a; // error
2D only: Is constructable from an angle specified in radians
float2d v = float2d::from_angle(0); // v contains 1, 0
Expression templates
Operations aren’t evaluated until applied to a value:
auto v = int3d{ 1, 2, 3 } + int3d{ 1, 2, 3 }; // v is of the intermediary type "operation"
Operations can be evaluated fully implicitly:
int3d v = int3d{ 1, 2, 3 } + int3d{ 1, 2, 3 }; // vector v contains 2, 4, 6
Or explicitly:
auto v = (int3d{ 1, 2, 3 } + int3d{ 1, 2, 3 }).evaluate(); // v is a vector and contains 2, 4, 6 // alternate syntax: auto v = *(int3d{ 1, 2, 3 } + int3d{ 1, 2, 3 }); // v is a vector and contains 2, 4, 6
Note
Throughout this documentation, vector expression
refers to an instance of either a vector value
(impl::value
) or a vector operation (impl::operation
)
Operator overloads
Note
All operators require the argument vector expressions (if more than one) to be of the same size
All operators evaluate the expressions component-wise
All binary arithmetic operators (
+
,-
,*
,/
,%
,&
,|
,^
,>>
,<<
), including their corresponding assignment operators, are overloaded for expressions of the pattern:[vector expression] [operator] [vector expression] [vector expression] [operator] [scalar]
All binary arithmetic operators, exluding their corresponding assignment operators, are overloaded for expressions of the pattern:
[scalar] [operator] [vector expression]
The unary operators
+
,-
, and~
are overloaded for all vector expressionsIs EqualityComparable: Two vectors are equal if all components are equal
float3d a { 1, 2, 3 }; float3d b = a; float3d c { 4, 5, 6 }; assert(a == b); assert(a != (b + c));
Is LessThanComparable: A vector
a
is “lesser than” a vectorb
if all components ina
are lesser than the corresponding components inb
Note
!(a < b)
does not imply thata >= b
int2d a { 1, 2 }; int2d b { 2, 3 }; assert(a < b); a.x = 2; assert_false(a < b); // since a.x >= b.x
Is explicitly convertable to a bool:
if (double2d{ 3, 4 }) std::cout << "This will run"; if (double2d::zero) std::cout << "This will not"; // explicit cast required bool is_nonzero = (bool)double2d{ 1, 0 }; // is_nonzero is true
Indexing
Components in all vector expressions can be retrieved either with
impl::expression_base::at()
:float3d v { 1, 2, 3 }; float x = v.at(0); // x is 1 float y = v.at(1); // y is 2
Or with the index operators:
float3d v { 1, 2, 3 }; float x = v[0]; // x is 1 float y = v[1]; // y is 2
If a compatible compiler is used, components in a vector value can also be accessed by name:
float3d v { 1, 2, 3 }; float x = v.x; // x is 1 float y = v.y; // y is 2
Or with a range-for loop:
int sum = 0; for (double v : double3d{ 1, 2, 3 }) sum += v; // sum is 6