40#ifndef GEOGRAM_BASIC_VECG
41#define GEOGRAM_BASIC_VECG
48#include <initializer_list>
73 template <index_t DIM,
class T>
90 for(
index_t i = 0; i < DIM; i++) {
109 for(
index_t i = 0; i < DIM; i++) {
115 template <
class T2, index_t DIM2>
120 for(
index_t i = 0; i < DIM; i++) {
135 for(
index_t i = 0; i < DIM; i++) {
144 vecng(
const std::initializer_list<T>& Vi) {
202 for(
index_t i = 0; i < DIM; i++) {
203 result += data_[i] * data_[i];
222 for(
index_t i = 0; i < DIM; i++) {
223 result +=
geo_sqr(v.data_[i] - data_[i]);
247 for(
index_t i = 0; i < DIM; i++) {
248 data_[i] += v.data_[i];
261 for(
index_t i = 0; i < DIM; i++) {
262 data_[i] -= v.data_[i];
278 for(
index_t i = 0; i < DIM; i++) {
295 for(
index_t i = 0; i < DIM; i++) {
310 for(
index_t i = 0; i < DIM; i++) {
311 result.data_[i] += v.data_[i];
325 for(
index_t i = 0; i < DIM; i++) {
326 result.data_[i] -= v.data_[i];
344 for(
index_t i = 0; i < DIM; i++) {
345 result.data_[i] /= T(s);
357 for(
index_t i = 0; i < DIM; i++) {
358 result.data_[i] = -data_[i];
374 template <index_t DIM,
class T>
379 for(
index_t i = 0; i < DIM; i++) {
380 result += v1[i] * v2[i];
398 class T2,
index_t DIM,
class T,
399 typename = std::enable_if_t<is_scalar<T2>::value>
404 for(
index_t i = 0; i < DIM; i++) {
405 result[i] = T(s) * v[i];
423 class T2,
index_t DIM,
class T,
424 typename = std::enable_if_t<is_scalar<T2>::value>
429 for(
index_t i = 0; i < DIM; i++) {
430 result[i] = T(s) * v[i];
445 template <index_t DIM,
class T>
457 template <index_t DIM,
class T>
470 template <index_t DIM,
class T>
485 template <index_t DIM,
class T>
501 template <index_t DIM,
class T> GEO_NODISCARD
522 template <index_t DIM,
class T>
526 return (T(1) - s) * v1 + s * v2;
557 vecng(
const T& x_in,
const T& y_in) :
589 vecng(
const std::initializer_list<T>& Vi) {
603 return x * x + y * y;
608 return sqrt(x * x + y * y);
615 return dx * dx + dy * dy;
721 return v1.x * v2.x + v1.y * v2.y;
735 return v1.x * v2.y - v1.y * v2.x;
745 typename = std::enable_if_t<is_scalar<T2>::value>
758 typename = std::enable_if_t<is_scalar<T2>::value>
795 vecng(
const T& x_in,
const T& y_in,
const T& z_in) :
805 vecng(T&& x_in, T&& y_in, T&& z_in) :
831 vecng(
const std::initializer_list<T>& Vi) {
846 template<
typename A,
typename B>
851 template<
typename A,
typename B>
856 template<
typename A,
typename B>
861 template<
typename A,
typename B>
872 return x * x + y * y + z * z;
877 return sqrt(x * x + y * y + z * z);
885 return dx * dx + dy * dy + dz * dz;
998 return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
1013 det2x2(v1.y, v2.y, v1.z, v2.z),
1014 det2x2(v1.z, v2.z, v1.x, v2.x),
1015 det2x2(v1.x, v2.x, v1.y, v2.y)
1026 typename = std::enable_if_t<is_scalar<T2>::value>
1030 return vecng<3, T>(T(s) * v.x, T(s) * v.y, T(s) * v.z);
1039 typename = std::enable_if_t<is_scalar<T2>::value>
1043 return vecng<3, T>(T(s) * v.x, T(s) * v.y, T(s) * v.z);
1078 vecng(
const T& x_in,
const T& y_in,
const T& z_in,
const T& w_in) :
1089 vecng(T&& x_in, T&& y_in, T&& z_in, T&& w_in) :
1118 vecng(
const std::initializer_list<T>& Vi) {
1132 template<
typename U>
1135 template<
typename X,
typename Y,
typename Z,
typename W>
1136 vecng(X _x, Y _y, Z _z, W _w);
1137 template<
typename X,
typename Y,
typename Z,
typename W>
1139 template<
typename X,
typename Y,
typename Z,
typename W>
1141 template<
typename X,
typename Y,
typename Z,
typename W>
1143 template<
typename X,
typename Y,
typename Z,
typename W>
1145 template<
typename X,
typename Y,
typename Z,
typename W>
1147 template<
typename X,
typename Y,
typename Z,
typename W>
1149 template<
typename X,
typename Y,
typename Z,
typename W>
1154 template<
typename X,
typename Y,
typename Z,
typename W>
1156 template<
typename X,
typename Y,
typename Z,
typename W>
1158 template<
typename X,
typename Y,
typename Z,
typename W>
1163 template<
typename X,
typename Y,
typename Z,
typename W>
1165 template<
typename X,
typename Y,
typename Z,
typename W>
1170 template<
typename X,
typename Y,
typename Z,
typename W>
1175 template<
typename X,
typename Y,
typename Z,
typename W>
1183 template<
typename A,
typename B,
typename C>
1185 template<
typename A,
typename B,
typename C>
1187 template<
typename A,
typename B,
typename C>
1189 template<
typename A,
typename B,
typename C>
1194 template<
typename A,
typename B,
typename C>
1196 template<
typename A,
typename B,
typename C>
1198 template<
typename A,
typename B,
typename C>
1200 template<
typename A,
typename B,
typename C>
1205 template<
typename A,
typename B,
typename C>
1207 template<
typename A,
typename B,
typename C>
1209 template<
typename A,
typename B,
typename C>
1211 template<
typename A,
typename B,
typename C>
1215 template<
typename A,
typename B>
1217 template<
typename A,
typename B>
1219 template<
typename A,
typename B>
1221 template<
typename A,
typename B>
1223 template<
typename A,
typename B>
1228 return x * x + y * y + z * z + w * w;
1233 return sqrt(x * x + y * y + z * z + w * w);
1242 return dx * dx + dy * dy + dz * dz + dw * dw;
1295 return vector_type(x + v.x, y + v.y, z + v.z, w + v.w);
1300 return vector_type(x - v.x, y - v.y, z - v.z, w - v.w);
1306 return vector_type(x / T(s), y / T(s), z / T(s), w / T(s));
1354 return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w;
1364 typename = std::enable_if_t<is_scalar<T2>::value>
1368 return vecng<4, T>(T(s) * v.x, T(s) * v.y, T(s) * v.z, T(s) * v.w);
1377 typename = std::enable_if_t<is_scalar<T2>::value>
1381 return vecng<4, T>(T(s) * v.x, T(s) * v.y, T(s) * v.z, T(s) * v.w);
1395 template <index_t DIM,
class T>
1399 const char* sep =
"";
1400 for(
index_t i = 0; i < DIM; i++) {
1417 template <index_t DIM,
class T>
1422 while(isspace(in.peek())) {
1425 if(in.peek() ==
'[' || in.peek() ==
'{') {
1428 while(isspace(in.peek())) {
1431 for(
index_t i = 0; i < DIM; i++) {
1433 while(isspace(in.peek())) {
1436 if(in.peek() ==
',') {
1439 while(isspace(in.peek())) {
1443 if(in.peek() ==
']' || in.peek() ==
'}') {
1452 template<
typename T>
1453 template<
typename A,
typename B>
1455 : x{static_cast<T>(_xy.x)}
1456 , y{static_cast<T>(_xy.y)}
1457 , z{static_cast<T>(_z)}
1460 template<
typename T>
1461 template<
typename A,
typename B>
1463 : x(static_cast<T>(_xy.x))
1464 , y(static_cast<T>(_xy.y))
1465 , z(static_cast<T>(_z.x))
1468 template<
typename T>
1469 template<
typename A,
typename B>
1471 : x(static_cast<T>(_x))
1472 , y(static_cast<T>(_yz.x))
1473 , z(static_cast<T>(_yz.y))
1476 template<
typename T>
1477 template<
typename A,
typename B>
1479 : x(static_cast<T>(_x.x))
1480 , y(static_cast<T>(_yz.x))
1481 , z(static_cast<T>(_yz.y))
1484 template<
typename T>
1485 template<
typename U>
1487 : x(static_cast<T>(v.x))
1488 , y(static_cast<T>(v.y))
1489 , z(static_cast<T>(v.z))
1494 template<
typename T>
1495 template<
typename U>
1497 : x(static_cast<T>(v.x))
1498 , y(static_cast<T>(v.x))
1499 , z(static_cast<T>(v.x))
1500 , w(static_cast<T>(v.x))
1503 template<
typename T>
1504 template<
typename X,
typename Y,
typename Z,
typename W>
1506 : x(static_cast<T>(_x))
1507 , y(static_cast<T>(_y))
1508 , z(static_cast<T>(_z))
1509 , w(static_cast<T>(_w))
1512 template<
typename T>
1513 template<
typename X,
typename Y,
typename Z,
typename W>
1515 : x(static_cast<T>(_x.x))
1516 , y(static_cast<T>(_y))
1517 , z(static_cast<T>(_z))
1518 , w(static_cast<T>(_w))
1521 template<
typename T>
1522 template<
typename X,
typename Y,
typename Z,
typename W>
1524 : x(static_cast<T>(_x))
1525 , y(static_cast<T>(_y.x))
1526 , z(static_cast<T>(_z))
1527 , w(static_cast<T>(_w))
1530 template<
typename T>
1531 template<
typename X,
typename Y,
typename Z,
typename W>
1533 : x(static_cast<T>(_x.x))
1534 , y(static_cast<T>(_y.x))
1535 , z(static_cast<T>(_z))
1536 , w(static_cast<T>(_w))
1539 template<
typename T>
1540 template<
typename X,
typename Y,
typename Z,
typename W>
1542 : x(static_cast<T>(_x))
1543 , y(static_cast<T>(_y))
1544 , z(static_cast<T>(_z.x))
1545 , w(static_cast<T>(_w))
1548 template<
typename T>
1549 template<
typename X,
typename Y,
typename Z,
typename W>
1551 : x(static_cast<T>(_x.x))
1552 , y(static_cast<T>(_y))
1553 , z(static_cast<T>(_z.x))
1554 , w(static_cast<T>(_w))
1557 template<
typename T>
1558 template<
typename X,
typename Y,
typename Z,
typename W>
1560 : x(static_cast<T>(_x))
1561 , y(static_cast<T>(_y.x))
1562 , z(static_cast<T>(_z.x))
1563 , w(static_cast<T>(_w))
1566 template<
typename T>
1567 template<
typename X,
typename Y,
typename Z,
typename W>
1569 const vecng<1, X>& _x,
const vecng<1, Y>& _y,
1570 const vecng<1, Z>& _z, W _w
1571 ) : x(static_cast<T>(_x.x))
1572 , y(static_cast<T>(_y.x))
1573 , z(static_cast<T>(_z.x))
1574 , w(static_cast<T>(_w))
1577 template<
typename T>
1578 template<
typename X,
typename Y,
typename Z,
typename W>
1580 const vecng<1, X>& _x, Y _y, Z _z,
const vecng<1, W>& _w
1581 ) : x(static_cast<T>(_x.x))
1582 , y(static_cast<T>(_y))
1583 , z(static_cast<T>(_z))
1584 , w(static_cast<T>(_w.x))
1587 template<
typename T>
1588 template<
typename X,
typename Y,
typename Z,
typename W>
1590 X _x,
const vecng<1, Y>& _y, Z _z,
const vecng<1, W>& _w
1591 ) : x(static_cast<T>(_x))
1592 , y(static_cast<T>(_y.x))
1593 , z(static_cast<T>(_z))
1594 , w(static_cast<T>(_w.x))
1597 template<
typename T>
1598 template<
typename X,
typename Y,
typename Z,
typename W>
1600 const vecng<1, X>& _x,
const vecng<1, Y>& _y, Z _z,
1601 const vecng<1, W>& _w
1602 ) : x(static_cast<T>(_x.x))
1603 , y(static_cast<T>(_y.x))
1604 , z(static_cast<T>(_z))
1605 , w(static_cast<T>(_w.x))
1608 template<
typename T>
1609 template<
typename X,
typename Y,
typename Z,
typename W>
1611 : x(static_cast<T>(_x))
1612 , y(static_cast<T>(_y))
1613 , z(static_cast<T>(_z.x))
1614 , w(static_cast<T>(_w.x))
1617 template<
typename T>
1618 template<
typename X,
typename Y,
typename Z,
typename W>
1620 const vecng<1, X>& _x, Y _y,
const vecng<1, Z>& _z,
1621 const vecng<1, W>& _w
1622 ) : x(static_cast<T>(_x.x))
1623 , y(static_cast<T>(_y))
1624 , z(static_cast<T>(_z.x))
1625 , w(static_cast<T>(_w.x))
1628 template<
typename T>
1629 template<
typename X,
typename Y,
typename Z,
typename W>
1631 X _x,
const vecng<1, Y>& _y,
const vecng<1, Z>& _z,
1632 const vecng<1, W>& _w
1633 ) : x(static_cast<T>(_x))
1634 , y(static_cast<T>(_y.x))
1635 , z(static_cast<T>(_z.x))
1636 , w(static_cast<T>(_w.x))
1639 template<
typename T>
1640 template<
typename X,
typename Y,
typename Z,
typename W>
1642 const vecng<1, X>& _x,
const vecng<1, Y>& _y,
1643 const vecng<1, Z>& _z,
const vecng<1, W>& _w
1644 ) : x(static_cast<T>(_x.x))
1645 , y(static_cast<T>(_y.x))
1646 , z(static_cast<T>(_z.x))
1647 , w(static_cast<T>(_w.x))
1652 template<
typename T>
1653 template<
typename A,
typename B,
typename C>
1655 : x(static_cast<T>(_xy.x))
1656 , y(static_cast<T>(_xy.y))
1657 , z(static_cast<T>(_z))
1658 , w(static_cast<T>(_w))
1661 template<
typename T>
1662 template<
typename A,
typename B,
typename C>
1664 : x(static_cast<T>(_xy.x))
1665 , y(static_cast<T>(_xy.y))
1666 , z(static_cast<T>(_z.x))
1667 , w(static_cast<T>(_w))
1670 template<
typename T>
1671 template<
typename A,
typename B,
typename C>
1673 : x(static_cast<T>(_xy.x))
1674 , y(static_cast<T>(_xy.y))
1675 , z(static_cast<T>(_z))
1676 , w(static_cast<T>(_w.x))
1679 template<
typename T>
1680 template<
typename A,
typename B,
typename C>
1682 const vecng<2, A>& _xy,
const vecng<1, B>& _z,
const vecng<1, C>& _w
1683 ) : x(static_cast<T>(_xy.x))
1684 , y(static_cast<T>(_xy.y))
1685 , z(static_cast<T>(_z.x))
1686 , w(static_cast<T>(_w.x))
1689 template<
typename T>
1690 template<
typename A,
typename B,
typename C>
1692 : x(static_cast<T>(_x))
1693 , y(static_cast<T>(_yz.x))
1694 , z(static_cast<T>(_yz.y))
1695 , w(static_cast<T>(_w))
1698 template<
typename T>
1699 template<
typename A,
typename B,
typename C>
1701 : x(static_cast<T>(_x.x))
1702 , y(static_cast<T>(_yz.x))
1703 , z(static_cast<T>(_yz.y))
1704 , w(static_cast<T>(_w))
1707 template<
typename T>
1708 template<
typename A,
typename B,
typename C>
1710 : x(static_cast<T>(_x))
1711 , y(static_cast<T>(_yz.x))
1712 , z(static_cast<T>(_yz.y))
1713 , w(static_cast<T>(_w.x))
1716 template<
typename T>
1717 template<
typename A,
typename B,
typename C>
1719 const vecng<1, A>& _x,
const vecng<2, B>& _yz,
const vecng<1, C>& _w
1720 ) : x(static_cast<T>(_x.x))
1721 , y(static_cast<T>(_yz.x))
1722 , z(static_cast<T>(_yz.y))
1723 , w(static_cast<T>(_w.x))
1726 template<
typename T>
1727 template<
typename A,
typename B,
typename C>
1729 : x(static_cast<T>(_x))
1730 , y(static_cast<T>(_y))
1731 , z(static_cast<T>(_zw.x))
1732 , w(static_cast<T>(_zw.y))
1735 template<
typename T>
1736 template<
typename A,
typename B,
typename C>
1738 : x(static_cast<T>(_x.x))
1739 , y(static_cast<T>(_y))
1740 , z(static_cast<T>(_zw.x))
1741 , w(static_cast<T>(_zw.y))
1744 template<
typename T>
1745 template<
typename A,
typename B,
typename C>
1747 : x(static_cast<T>(_x))
1748 , y(static_cast<T>(_y.x))
1749 , z(static_cast<T>(_zw.x))
1750 , w(static_cast<T>(_zw.y))
1753 template<
typename T>
1754 template<
typename A,
typename B,
typename C>
1756 const vecng<1, A>& _x,
const vecng<1, B>& _y,
const vecng<2, C>& _zw
1757 ) : x(static_cast<T>(_x.x))
1758 , y(static_cast<T>(_y.x))
1759 , z(static_cast<T>(_zw.x))
1760 , w(static_cast<T>(_zw.y))
1763 template<
typename T>
1764 template<
typename A,
typename B>
1766 : x(static_cast<T>(_xyz.x))
1767 , y(static_cast<T>(_xyz.y))
1768 , z(static_cast<T>(_xyz.z))
1769 , w(static_cast<T>(_w))
1772 template<
typename T>
1773 template<
typename A,
typename B>
1775 : x(static_cast<T>(_xyz.x))
1776 , y(static_cast<T>(_xyz.y))
1777 , z(static_cast<T>(_xyz.z))
1778 , w(static_cast<T>(_w.x))
1781 template<
typename T>
1782 template<
typename A,
typename B>
1784 : x(static_cast<T>(_x))
1785 , y(static_cast<T>(_yzw.x))
1786 , z(static_cast<T>(_yzw.y))
1787 , w(static_cast<T>(_yzw.z))
1790 template<
typename T>
1791 template<
typename A,
typename B>
1793 : x(static_cast<T>(_x.x))
1794 , y(static_cast<T>(_yzw.x))
1795 , z(static_cast<T>(_yzw.y))
1796 , w(static_cast<T>(_yzw.z))
1799 template<
typename T>
1800 template<
typename A,
typename B>
1802 : x(static_cast<T>(_xy.x))
1803 , y(static_cast<T>(_xy.y))
1804 , z(static_cast<T>(_zw.x))
1805 , w(static_cast<T>(_zw.y))
Assertion checking mechanism.
#define geo_debug_assert(x)
Verifies that a condition is met.
T distance2(const vector_type &v) const
vecng(const T &x_in, const T &y_in)
Constructs a vector from coordinates.
T distance(const vector_type &v) const
T * data()
Gets modifiable vector data.
index_t dimension() const
Gets the vector dimension.
const T * data() const
Gets non-modifiable vector data.
void optimize()
Optimizes coordinate representation.
vecng(const vecng< dim, T2 > &v)
Constructs a vector by copy.
T length() const
Gets the length of the vector.
vecng(const std::initializer_list< T > &Vi)
T value_type
The type of the vector coordinates.
vecng(T &&x_in, T &&y_in)
Constructs a vector from coordinates.
vecng()
Default vector constructor.
vecng(const T2 *v)
Constructs a vector from an array.
vecng< dim, T > vector_type
This vector type.
T length2() const
Gets the squared length of the vector.
vecng(const vecng< dim, T2 > &v)
Constructs a vector by copy.
void optimize()
Optimizes coordinate representation.
vecng()
Default vector constructor.
vecng(T &&x_in, T &&y_in, T &&z_in)
Constructs a vector from coordinates.
T * data()
Gets modifiable vector data.
T value_type
The type of the vector coordinates.
T distance2(const vector_type &v) const
const T * data() const
Gets non-modifiable vector data.
T length2() const
Gets the squared length of the vector.
vecng(const T2 *v)
Constructs a vector from an array.
vecng(const std::initializer_list< T > &Vi)
vecng< dim, T > vector_type
This vector type.
T distance(const vector_type &v) const
index_t dimension() const
Gets the vector dimension.
T length() const
Gets the length of the vector.
vecng(const T &x_in, const T &y_in, const T &z_in)
Constructs a vector from coordinates.
T distance2(const vector_type &v) const
vecng(const std::initializer_list< T > &Vi)
vecng(const T &x_in, const T &y_in, const T &z_in, const T &w_in)
Constructs a vector from coordinates.
T length2() const
Gets the squared length of the vector.
vecng< dim, T > vector_type
This vector type.
T value_type
The type of the vector coordinates.
vecng()
Default vector constructor.
const T * data() const
Gets non-modifiable vector data.
index_t dimension() const
Gets the vector dimension.
vecng(const T2 *v)
Constructs a vector from an array.
T * data()
Gets modifiable vector data.
T length() const
Gets the length of the vector.
vecng(T &&x_in, T &&y_in, T &&z_in, T &&w_in)
Constructs a vector from coordinates.
T distance(const vector_type &v) const
vecng(const vecng< dim, T2 > &v)
Constructs a vector by copy.
T & operator[](index_t i)
Gets a modifiable vector coordinate.
vector_type & operator-=(const vector_type &v)
Subtracts a vector in place.
vecng< 3, T > cross(const vecng< 3, T > &v1, const vecng< 3, T > &v2)
Computes the cross product of 2 vectors.
T value_type
The type of the vector coordinates.
T length2(const vecng< DIM, T > &v)
Gets the square norm of a vector.
T det(const vecng< 2, T > &v1, const vecng< 2, T > &v2)
Computes the determinant of 2 vectors.
T distance2(const vecng< DIM, T > &v1, const vecng< DIM, T > &v2)
Gets the square distance between 2 vectors.
T length2() const
Gets the squared length of the vector.
T * data()
Gets modifiable vector data.
vector_type & operator/=(T2 s)
Divides by a scalar in place.
GEO_NODISCARD vecng< DIM, T > normalize(const vecng< DIM, T > &v)
Normalizes a vector.
T dot(const vecng< 4, T > &v1, const vecng< 4, T > &v2)
Computes the dot product of 2 vectors.
T length() const
Gets the length of the vector.
const T * data() const
Gets non-modifiable vector data.
T length(const vecng< DIM, T > &v)
Gets the norm of a vector.
index_t dimension() const
Gets the vector dimension.
vector_type operator-() const
Negates a vector.
vector_type & operator*=(T2 s)
Multiplies by a scalar in place.
vector_type operator+(const vector_type &v) const
Adds 2 vectors.
vector_type operator/(T2 s) const
Divides a vector by a scalar.
vector_type & operator+=(const vector_type &v)
Adds a vector in place.
vecng()
Default vector constructor.
vecng< DIM, T > vector_type
This vector type.
T dot(const vecng< 2, T > &v1, const vecng< 2, T > &v2)
Computes the dot product of 2 vectors.
vecng< DIM, T > mix(const vecng< DIM, T > &v1, const vecng< DIM, T > &v2, T s)
Computes a weighted barycenter.
T distance(const vecng< DIM, T > &v1, const vecng< DIM, T > &v2)
Gets the distance between 2 vectors.
T distance(const vector_type &v) const
Gets the distance to a vector.
vecng(const vecng< DIM, T2 > &v)
Constructs a vector by copy.
T distance2(const vector_type &v) const
Gets the squared distance to a vector.
vecng(const std::initializer_list< T > &Vi)
Constructs a vector from an initializer list.
vecng(const T2 *v)
Constructs a vector from an array.
static constexpr index_t dim
The dimension of the vector.
T dot(const vecng< DIM, T > &v1, const vecng< DIM, T > &v2)
Computes the dot product of 2 vectors.
Determinants for small sizes.
Common include file, providing basic definitions. Should be included before anything else by all head...
Types and functions for memory manipulation.
void optimize_number_representation(T &x)
place holder for optimizing internal number representation
Global Vorpaline namespace.
T dot(const vecng< 3, T > &v1, const vecng< 3, T > &v2)
Computes the dot product of 2 vectors. vecng
std::istream & operator>>(std::istream &in, Quaternion &q)
Reads a Quaternion from a stream.
T geo_sqr(T x)
Gets the square value of a value.
std::ostream & operator<<(std::ostream &out, const Quaternion &q)
Writes a Quaternion to a stream.
geo_index_t index_t
The type for storing and manipulating indices.
T det2x2(const T &a11, const T &a12, const T &a21, const T &a22)
Computes a two-by-two determinant.
vecng< DIM, FT > operator*(const Matrix< DIM, FT > &M, const vecng< DIM, FT > &x)
Computes a matrix vector product.
Types and functions for numbers manipulation.