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))
1492 template<
typename T>
1493 template<
typename U>
1495 : x(static_cast<T>(v.x))
1496 , y(static_cast<T>(v.x))
1497 , z(static_cast<T>(v.x))
1498 , w(static_cast<T>(v.x))
1501 template<
typename T>
1502 template<
typename X,
typename Y,
typename Z,
typename W>
1504 : x(static_cast<T>(_x))
1505 , y(static_cast<T>(_y))
1506 , z(static_cast<T>(_z))
1507 , w(static_cast<T>(_w))
1510 template<
typename T>
1511 template<
typename X,
typename Y,
typename Z,
typename W>
1513 : x(static_cast<T>(_x.x))
1514 , y(static_cast<T>(_y))
1515 , z(static_cast<T>(_z))
1516 , w(static_cast<T>(_w))
1519 template<
typename T>
1520 template<
typename X,
typename Y,
typename Z,
typename W>
1522 : x(static_cast<T>(_x))
1523 , y(static_cast<T>(_y.x))
1524 , z(static_cast<T>(_z))
1525 , w(static_cast<T>(_w))
1528 template<
typename T>
1529 template<
typename X,
typename Y,
typename Z,
typename W>
1531 : x(static_cast<T>(_x.x))
1532 , y(static_cast<T>(_y.x))
1533 , z(static_cast<T>(_z))
1534 , w(static_cast<T>(_w))
1537 template<
typename T>
1538 template<
typename X,
typename Y,
typename Z,
typename W>
1540 : x(static_cast<T>(_x))
1541 , y(static_cast<T>(_y))
1542 , z(static_cast<T>(_z.x))
1543 , w(static_cast<T>(_w))
1546 template<
typename T>
1547 template<
typename X,
typename Y,
typename Z,
typename W>
1549 : x(static_cast<T>(_x.x))
1550 , y(static_cast<T>(_y))
1551 , z(static_cast<T>(_z.x))
1552 , w(static_cast<T>(_w))
1555 template<
typename T>
1556 template<
typename X,
typename Y,
typename Z,
typename W>
1558 : x(static_cast<T>(_x))
1559 , y(static_cast<T>(_y.x))
1560 , z(static_cast<T>(_z.x))
1561 , w(static_cast<T>(_w))
1564 template<
typename T>
1565 template<
typename X,
typename Y,
typename Z,
typename W>
1567 const vecng<1, X>& _x,
const vecng<1, Y>& _y,
1568 const vecng<1, Z>& _z, W _w
1569 ) : x(static_cast<T>(_x.x))
1570 , y(static_cast<T>(_y.x))
1571 , z(static_cast<T>(_z.x))
1572 , w(static_cast<T>(_w))
1575 template<
typename T>
1576 template<
typename X,
typename Y,
typename Z,
typename W>
1578 const vecng<1, X>& _x, Y _y, Z _z,
const vecng<1, W>& _w
1579 ) : x(static_cast<T>(_x.x))
1580 , y(static_cast<T>(_y))
1581 , z(static_cast<T>(_z))
1582 , w(static_cast<T>(_w.x))
1585 template<
typename T>
1586 template<
typename X,
typename Y,
typename Z,
typename W>
1588 X _x,
const vecng<1, Y>& _y, Z _z,
const vecng<1, W>& _w
1589 ) : x(static_cast<T>(_x))
1590 , y(static_cast<T>(_y.x))
1591 , z(static_cast<T>(_z))
1592 , w(static_cast<T>(_w.x))
1595 template<
typename T>
1596 template<
typename X,
typename Y,
typename Z,
typename W>
1598 const vecng<1, X>& _x,
const vecng<1, Y>& _y, Z _z,
1599 const vecng<1, W>& _w
1600 ) : x(static_cast<T>(_x.x))
1601 , y(static_cast<T>(_y.x))
1602 , z(static_cast<T>(_z))
1603 , w(static_cast<T>(_w.x))
1606 template<
typename T>
1607 template<
typename X,
typename Y,
typename Z,
typename W>
1609 : x(static_cast<T>(_x))
1610 , y(static_cast<T>(_y))
1611 , z(static_cast<T>(_z.x))
1612 , w(static_cast<T>(_w.x))
1615 template<
typename T>
1616 template<
typename X,
typename Y,
typename Z,
typename W>
1618 const vecng<1, X>& _x, Y _y,
const vecng<1, Z>& _z,
1619 const vecng<1, W>& _w
1620 ) : x(static_cast<T>(_x.x))
1621 , y(static_cast<T>(_y))
1622 , z(static_cast<T>(_z.x))
1623 , w(static_cast<T>(_w.x))
1626 template<
typename T>
1627 template<
typename X,
typename Y,
typename Z,
typename W>
1629 X _x,
const vecng<1, Y>& _y,
const vecng<1, Z>& _z,
1630 const vecng<1, W>& _w
1631 ) : x(static_cast<T>(_x))
1632 , y(static_cast<T>(_y.x))
1633 , z(static_cast<T>(_z.x))
1634 , w(static_cast<T>(_w.x))
1637 template<
typename T>
1638 template<
typename X,
typename Y,
typename Z,
typename W>
1640 const vecng<1, X>& _x,
const vecng<1, Y>& _y,
1641 const vecng<1, Z>& _z,
const vecng<1, W>& _w
1642 ) : x(static_cast<T>(_x.x))
1643 , y(static_cast<T>(_y.x))
1644 , z(static_cast<T>(_z.x))
1645 , w(static_cast<T>(_w.x))
1650 template<
typename T>
1651 template<
typename A,
typename B,
typename C>
1653 : x(static_cast<T>(_xy.x))
1654 , y(static_cast<T>(_xy.y))
1655 , z(static_cast<T>(_z))
1656 , w(static_cast<T>(_w))
1659 template<
typename T>
1660 template<
typename A,
typename B,
typename C>
1662 : x(static_cast<T>(_xy.x))
1663 , y(static_cast<T>(_xy.y))
1664 , z(static_cast<T>(_z.x))
1665 , w(static_cast<T>(_w))
1668 template<
typename T>
1669 template<
typename A,
typename B,
typename C>
1671 : x(static_cast<T>(_xy.x))
1672 , y(static_cast<T>(_xy.y))
1673 , z(static_cast<T>(_z))
1674 , w(static_cast<T>(_w.x))
1677 template<
typename T>
1678 template<
typename A,
typename B,
typename C>
1680 const vecng<2, A>& _xy,
const vecng<1, B>& _z,
const vecng<1, C>& _w
1681 ) : x(static_cast<T>(_xy.x))
1682 , y(static_cast<T>(_xy.y))
1683 , z(static_cast<T>(_z.x))
1684 , w(static_cast<T>(_w.x))
1687 template<
typename T>
1688 template<
typename A,
typename B,
typename C>
1690 : x(static_cast<T>(_x))
1691 , y(static_cast<T>(_yz.x))
1692 , z(static_cast<T>(_yz.y))
1693 , w(static_cast<T>(_w))
1696 template<
typename T>
1697 template<
typename A,
typename B,
typename C>
1699 : x(static_cast<T>(_x.x))
1700 , y(static_cast<T>(_yz.x))
1701 , z(static_cast<T>(_yz.y))
1702 , w(static_cast<T>(_w))
1705 template<
typename T>
1706 template<
typename A,
typename B,
typename C>
1708 : x(static_cast<T>(_x))
1709 , y(static_cast<T>(_yz.x))
1710 , z(static_cast<T>(_yz.y))
1711 , w(static_cast<T>(_w.x))
1714 template<
typename T>
1715 template<
typename A,
typename B,
typename C>
1717 const vecng<1, A>& _x,
const vecng<2, B>& _yz,
const vecng<1, C>& _w
1718 ) : x(static_cast<T>(_x.x))
1719 , y(static_cast<T>(_yz.x))
1720 , z(static_cast<T>(_yz.y))
1721 , w(static_cast<T>(_w.x))
1724 template<
typename T>
1725 template<
typename A,
typename B,
typename C>
1727 : x(static_cast<T>(_x))
1728 , y(static_cast<T>(_y))
1729 , z(static_cast<T>(_zw.x))
1730 , w(static_cast<T>(_zw.y))
1733 template<
typename T>
1734 template<
typename A,
typename B,
typename C>
1736 : x(static_cast<T>(_x.x))
1737 , y(static_cast<T>(_y))
1738 , z(static_cast<T>(_zw.x))
1739 , w(static_cast<T>(_zw.y))
1742 template<
typename T>
1743 template<
typename A,
typename B,
typename C>
1745 : x(static_cast<T>(_x))
1746 , y(static_cast<T>(_y.x))
1747 , z(static_cast<T>(_zw.x))
1748 , w(static_cast<T>(_zw.y))
1751 template<
typename T>
1752 template<
typename A,
typename B,
typename C>
1754 const vecng<1, A>& _x,
const vecng<1, B>& _y,
const vecng<2, C>& _zw
1755 ) : x(static_cast<T>(_x.x))
1756 , y(static_cast<T>(_y.x))
1757 , z(static_cast<T>(_zw.x))
1758 , w(static_cast<T>(_zw.y))
1761 template<
typename T>
1762 template<
typename A,
typename B>
1764 : x(static_cast<T>(_xyz.x))
1765 , y(static_cast<T>(_xyz.y))
1766 , z(static_cast<T>(_xyz.z))
1767 , w(static_cast<T>(_w))
1770 template<
typename T>
1771 template<
typename A,
typename B>
1773 : x(static_cast<T>(_xyz.x))
1774 , y(static_cast<T>(_xyz.y))
1775 , z(static_cast<T>(_xyz.z))
1776 , w(static_cast<T>(_w.x))
1779 template<
typename T>
1780 template<
typename A,
typename B>
1782 : x(static_cast<T>(_x))
1783 , y(static_cast<T>(_yzw.x))
1784 , z(static_cast<T>(_yzw.y))
1785 , w(static_cast<T>(_yzw.z))
1788 template<
typename T>
1789 template<
typename A,
typename B>
1791 : x(static_cast<T>(_x.x))
1792 , y(static_cast<T>(_yzw.x))
1793 , z(static_cast<T>(_yzw.y))
1794 , w(static_cast<T>(_yzw.z))
1797 template<
typename T>
1798 template<
typename A,
typename B>
1800 : x(static_cast<T>(_xy.x))
1801 , y(static_cast<T>(_xy.y))
1802 , z(static_cast<T>(_zw.x))
1803 , 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.