- Adjusted Formatting of tests

- Finished map implementation and unit tests

 TODO: Threading
This commit is contained in:
2025-07-23 12:05:02 -04:00
parent 73333b4c67
commit 5ab2952e83
63 changed files with 2703 additions and 2187 deletions

View File

@@ -31,6 +31,7 @@ set(FENNEC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
# include scripts # include scripts
include("${FENNEC_SOURCE_DIR}/cmake/platform.cmake") include("${FENNEC_SOURCE_DIR}/cmake/platform.cmake")
include("${FENNEC_SOURCE_DIR}/cmake/build.cmake") include("${FENNEC_SOURCE_DIR}/cmake/build.cmake")
include("${FENNEC_SOURCE_DIR}/cmake/compiler.cmake")
# find dependencies # find dependencies
find_package(Doxygen) find_package(Doxygen)
@@ -170,6 +171,9 @@ add_library(fennec STATIC
${FENNEC_EXTRA_SOURCES} ${FENNEC_EXTRA_SOURCES}
include/fennec/lang/type_operators.h
include/fennec/containers/tuple.h
include/fennec/containers/detail/__tuple.h
) )
add_dependencies(fennec metaprogramming) add_dependencies(fennec metaprogramming)

16
READINGS.md Normal file
View File

@@ -0,0 +1,16 @@
# Readings
Here is a list of relevant books and articles on various concepts related to
developing a game engine and its subsystems.
- Game Engine Architecture, Ed. 3 – Jason Gregory
- https://www.gameenginebook.com/
- OpenGL 4 Shading Language Cookbook, Ed. 3 – David A. Wolff
- https://www.packtpub.com/en-us/product/opengl-4-shading-language-cookbook-9781789340662
- Design Patterns: Elements of Reusable Object-Oriented Software – Erich Gamma, Richard Helm, Ralph Johnson, John Vilssides
- https://www.oreilly.com/library/view/design-patterns-elements/0201633612/
- Head First Design Patterns – Eric FReeman, Elisabeth Robson, Bert Bates, Kathy Sierra
- https://www.oreilly.com/library/view/head-first-design/0596007124/

View File

@@ -16,8 +16,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
# ====================================================================================================================== # ======================================================================================================================
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_COMPILER_GCC=0)
if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
set(FENNEC_COMPILER "GCC") set(FENNEC_COMPILER "GCC")
include("${FENNEC_SOURCE_DIR}/cmake/gcc.cmake") include("${FENNEC_SOURCE_DIR}/cmake/gcc.cmake")

View File

@@ -20,4 +20,4 @@ add_compile_options("-mxsave" "-Wall" "-Wextra" "-pedantic" "-Werror")
set(FENNEC_PRIVATE_LINK_OPTIONS "-nostdlib" "-fno-exceptions" "-fno-rtti" "-fdiagnostics-all-candidates") set(FENNEC_PRIVATE_LINK_OPTIONS "-nostdlib" "-fno-exceptions" "-fno-rtti" "-fdiagnostics-all-candidates")
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_COMPILER=FENNEC_COMPILER_GCC) list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_COMPILER_GCC=1)

View File

@@ -18,6 +18,9 @@
macro(fennec_check_platform) macro(fennec_check_platform)
# unix
include("${FENNEC_SOURCE_DIR}/cmake/unix.cmake")
# compile definitions # compile definitions
list(APPEND FENNEC_COMPILE_DEFINITIONS list(APPEND FENNEC_COMPILE_DEFINITIONS
FENNEC_PLATFORM_NAME="Linux" FENNEC_PLATFORM_NAME="Linux"
@@ -30,8 +33,8 @@ macro(fennec_check_platform)
) )
# includes # includes
include("${FENNEC_SOURCE_DIR}/cmake/libwayland.cmake") include("${FENNEC_SOURCE_DIR}/cmake/wayland.cmake")
# tests # tests
fennec_check_libwayland() fennec_check_wayland()
endmacro() endmacro()

22
cmake/unix.cmake Normal file
View File

@@ -0,0 +1,22 @@
# ======================================================================================================================
# fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# ======================================================================================================================
# compile definitions
list(APPEND FENNEC_COMPILE_DEFINITIONS
FENNEC_PLATFORM_UNIX=1
)

View File

@@ -18,7 +18,7 @@
# https://gist.github.com/mariobadr/acc3c8adf4b4e722705be38c3deac59a # https://gist.github.com/mariobadr/acc3c8adf4b4e722705be38c3deac59a
macro(fennec_check_libwayland) macro(fennec_check_wayland)
set(WAYLAND_CLIENT_FOUND 0) set(WAYLAND_CLIENT_FOUND 0)
find_path( find_path(

View File

@@ -48,7 +48,7 @@ PROJECT_NAME = fennec
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = PROJECT_NUMBER = 1.0.2
# Using the PROJECT_BRIEF tag one can provide an optional one line description # Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a # for a project that appears at the top of each page and should give viewer a

View File

@@ -0,0 +1,59 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_CONTAINERS_DETAIL_TUPLE_H
#define FENNEC_CONTAINERS_DETAIL_TUPLE_H
#include <fennec/lang/sequences.h>
#include <fennec/lang/utility.h>
namespace fennec::detail
{
// leaves
template<size_t i, typename T>
struct __tuple_leaf {
T value;
template<typename...ArgsT>
__tuple_leaf(ArgsT&&...args) : value(args...) {
}
constexpr operator T&() {
return value;
}
constexpr operator const T&() const {
return value;
}
};
// proxy
template<typename, typename...TypesT>
struct __tuple;
template<size_t...i, typename...TypesT>
struct __tuple<index_sequence<i...>, TypesT...> : __tuple_leaf<i, TypesT>... {
template<typename...ArgsT>
__tuple(ArgsT&&...args) : __tuple_leaf<i, TypesT>(args)... {
}
};
}
#endif // FENNEC_CONTAINERS_DETAIL_TUPLE_H

View File

@@ -27,6 +27,24 @@ namespace fennec
// TODO: Document // TODO: Document
/* Ramblings
*
* Definitions:
* user = Programmer using this data structure
*
* The STL unordered-map is very contrived. Some of its functionality encourages younger programmers to use
* the exception model. Ideally, I would like this structure to never throw an error with typical use.
*
* The array access operator is, in my opinion, poorly implemented. I do not think that this operator should handle
* insertions and should handle access only. This is the only data structure in STL that has this behavior, no other
* data structure modifies contents by inherently calling operator[].
*
* Currently, I am considering implementing this as the following:
* Access will be handled only via operator[]. Return value will be an optional which forces user validation.
* Insertions will be handled only via an insert/emplace function.
* Deletions will be handled only via an erase function.
*/
template<typename KeyT, typename ValueT, typename Hash = hash<KeyT>, typename Alloc = allocator<pair<KeyT, ValueT>>> template<typename KeyT, typename ValueT, typename Hash = hash<KeyT>, typename Alloc = allocator<pair<KeyT, ValueT>>>
struct map { struct map {
public: public:
@@ -36,13 +54,136 @@ public:
using alloc_t = typename allocator_traits<Alloc>::template rebind<elem_t>; using alloc_t = typename allocator_traits<Alloc>::template rebind<elem_t>;
using hash_t = Hash; using hash_t = Hash;
map() = default; // We only want to hash the key
~map() = default; struct key_hash : hash_t {
constexpr size_t operator()(const elem_t& p) const {
return hash_t::operator()(p.first);
}
};
// We only want to compare the keys
struct node_equals : equality<KeyT> {
constexpr bool operator()(const elem_t& a, const elem_t& b) const {
return equality<KeyT>::operator()(a.first, b.first);
}
};
constexpr map() = default;
constexpr ~map() = default;
constexpr value_t* operator[](const KeyT& key) {
union U { // Hacky way of avoiding constructing the value, TODO: Check for warnings on other compilers
pair<KeyT, char[sizeof(ValueT)]> root;
pair<KeyT, ValueT> val;
~U() {
root.~pair<KeyT, char[sizeof(ValueT)]>();
}
} trick = { .root = { key, 0 } };
auto it = _set.find(trick.val);
if (it == _set.end()) {
return nullptr;
}
return &_set.at(it)->second;
}
constexpr const value_t* operator[](const KeyT& key) const {
union U { // Hacky way of avoiding constructing the value, TODO: Check for warnings on other compilers
pair<KeyT, char[sizeof(ValueT)]> root;
pair<KeyT, ValueT> val;
~U() {
root.~pair<KeyT, char[sizeof(ValueT)]>();
}
} trick = { .root = { key, 0 } }; // Only initialize root
auto it = _set.find(trick.val);
if (it == _set.end()) {
return nullptr;
}
return &_set.at(it)->second;
}
template<typename...ArgsT>
constexpr value_t* operator[](ArgsT&&...args) {
union U { // Hacky way of avoiding constructing the value, TODO: Check for warnings on other compilers
pair<KeyT, char[sizeof(ValueT)]> root;
pair<KeyT, ValueT> val;
~U() {
root.~pair<KeyT, char[sizeof(ValueT)]>();
}
} trick = { .root = { key_t(fennec::forward<ArgsT>(args)...), 0 } }; // Only initialize root
auto it = _set.find(trick.val);
if (it == _set.end()) {
return nullptr;
}
return &_set.at(it)->second;
}
template<typename...ArgsT>
constexpr const value_t* operator[](ArgsT&&...args) const {
union U { // Hacky way of avoiding constructing the value, TODO: Check for warnings on other compilers
pair<KeyT, char[sizeof(ValueT)]> root;
pair<KeyT, ValueT> val;
~U() {
root.~pair<KeyT, char[sizeof(ValueT)]>();
}
} trick = { .root = { key_t(fennec::forward<ArgsT>(args)...), 0 } }; // Only initialize root
auto it = _set.find(trick.val);
if (it == _set.end()) {
return nullptr;
}
return &_set.at(it)->second;
}
constexpr void insert(elem_t&& pair) {
auto it = _set.find(pair);
if (it == _set.end()) {
_set.at(it)->second = fennec::move(pair.second);
return;
}
_set.insert(fennec::forward<elem_t>(pair));
}
template<typename...ArgsT>
constexpr void emplace(ArgsT&&...args) {
_set.insert(elem_t(args...));
}
constexpr void erase(KeyT&& key) {
union U { // Hacky way of avoiding constructing the value, TODO: Check for warnings on other compilers
pair<KeyT, char[sizeof(ValueT)]> root;
pair<KeyT, ValueT> val;
~U() {
root.~pair<KeyT, char[sizeof(ValueT)]>();
}
} trick = { .root = { fennec::forward<KeyT>(key), 0 } };
_set.erase(trick.val);
}
constexpr void erase(const KeyT& key) {
KeyT val = key;
erase(fennec::move(val));
}
template<typename...ArgsT>
constexpr void erase(ArgsT&&...args) {
union U { // Hacky way of avoiding constructing the value, TODO: Check for warnings on other compilers
pair<KeyT, char[sizeof(ValueT)]> root;
pair<KeyT, ValueT> val;
~U() {
root.~pair<KeyT, char[sizeof(ValueT)]>();
}
} trick = { .root = { KeyT(fennec::forward<ArgsT>(args)...), 0 } };
_set.erase(trick.val);
}
private: private:
set<elem_t, hash_t, alloc_t> _set; set<elem_t, key_hash, node_equals, alloc_t> _set;
}; };
} }

View File

@@ -39,6 +39,10 @@ template<typename T>
struct optional { struct optional {
public: public:
// Constructors ======================================================================================================== // Constructors ========================================================================================================
using reference_t = T&;
using pointer_t = add_pointer_t<remove_reference_t<T>>;
using const_reference_t = const T&;
using const_pointer_t = const add_pointer_t<remove_reference_t<T>>;
/// ///
/// \brief Default Constructor /// \brief Default Constructor
@@ -203,11 +207,11 @@ public:
return _set; return _set;
} }
constexpr T* operator->() noexcept { constexpr pointer_t operator->() noexcept {
return _set ? &_val : nullptr; return _set ? &_val : nullptr;
} }
constexpr const T* operator->() const noexcept { constexpr const pointer_t operator->() const noexcept {
return _set ? &_val : nullptr; return _set ? &_val : nullptr;
} }

View File

@@ -19,6 +19,7 @@
#ifndef FENNEC_CONTAINERS_PAIR_H #ifndef FENNEC_CONTAINERS_PAIR_H
#define FENNEC_CONTAINERS_PAIR_H #define FENNEC_CONTAINERS_PAIR_H
#include <fennec/containers/tuple.h>
#include <fennec/lang/hashing.h> #include <fennec/lang/hashing.h>
#include <fennec/lang/utility.h> #include <fennec/lang/utility.h>
@@ -42,6 +43,12 @@ struct pair {
, second(fennec::forward<T1>(y)) { , second(fennec::forward<T1>(y)) {
} }
template<typename Arg1T, typename Arg2T>
constexpr pair(Arg1T&& arg1, Arg2T&& arg2)
: first(fennec::forward<Arg1T>(arg1))
, second(fennec::forward<Arg2T>(arg2)) {
}
constexpr pair(const pair&) = default; constexpr pair(const pair&) = default;
constexpr pair(pair&&) noexcept = default; constexpr pair(pair&&) noexcept = default;

View File

@@ -22,6 +22,7 @@
// https://programming.guide/robin-hood-hashing.html // https://programming.guide/robin-hood-hashing.html
#include <fennec/containers/optional.h> #include <fennec/containers/optional.h>
#include <fennec/lang/compare.h>
#include <fennec/math/ext/primes.h> #include <fennec/math/ext/primes.h>
#include <fennec/memory/allocator.h> #include <fennec/memory/allocator.h>
#include <fennec/lang/hashing.h> #include <fennec/lang/hashing.h>
@@ -31,15 +32,17 @@ namespace fennec
// TODO: Document // TODO: Document
template<typename T, class Hash = hash<T>, class Alloc = allocator<T>> template<typename T, class Hash = hash<T>, class Equals = equality<T>, class Alloc = allocator<T>>
struct set { struct set {
public: public:
using alloc_t = typename allocator_traits<Alloc>::template rebind<T>; using alloc_t = typename allocator_traits<Alloc>::template rebind<T>;
using hash_t = Hash; using hash_t = Hash;
using equal_t = Equals;
using elem_t = T; using elem_t = T;
class iterator; class iterator;
static constexpr size_t npos = -1; static constexpr size_t npos = -1;
static constexpr double default_load = 0.8;
private: private:
struct node { struct node {
@@ -54,60 +57,71 @@ public:
constexpr set() constexpr set()
: _alloc() : _alloc()
, _hash() , _hash()
, _size(0) { , _size(0)
, _load(default_load) {
}; };
constexpr set(const hash_t& hash) constexpr set(const hash_t& hash)
: _alloc() : _alloc()
, _hash(hash) , _hash(hash)
, _size(0) { , _size(0)
, _load(default_load) {
} }
constexpr set(hash_t&& hash) noexcept constexpr set(hash_t&& hash) noexcept
: _alloc() : _alloc()
, _hash(hash) , _hash(hash)
, _size(0) { , _size(0)
, _load(default_load) {
} }
constexpr set(const alloc_t& alloc) constexpr set(const alloc_t& alloc)
: _alloc(alloc) : _alloc(alloc)
, _hash() , _hash()
, _size(0) { , _size(0)
, _load(default_load) {
} }
constexpr set(alloc_t&& alloc) noexcept constexpr set(alloc_t&& alloc) noexcept
: _alloc(alloc) : _alloc(alloc)
, _hash() , _hash()
, _size(0) { , _size(0)
, _load(default_load) {
} }
constexpr set(const hash_t& hash, const alloc_t& alloc) constexpr set(const hash_t& hash, const alloc_t& alloc)
: _alloc(alloc) : _alloc(alloc)
, _hash(hash) , _hash(hash)
, _size(0) { , _size(0)
, _load(default_load) {
} }
constexpr set(const hash_t& hash, alloc_t&& alloc) noexcept constexpr set(const hash_t& hash, alloc_t&& alloc) noexcept
: _alloc(alloc) : _alloc(alloc)
, _hash(hash) , _hash(hash)
, _size(0) { , _size(0)
, _load(default_load) {
} }
constexpr set(hash_t&& hash, alloc_t&& alloc) noexcept constexpr set(hash_t&& hash, alloc_t&& alloc) noexcept
: _alloc(alloc) : _alloc(alloc)
, _hash(hash) , _hash(hash)
, _size(0) { , _size(0)
, _load(default_load) {
} }
constexpr set(hash_t&& hash, const alloc_t& alloc) noexcept constexpr set(hash_t&& hash, const alloc_t& alloc) noexcept
: _alloc(alloc) : _alloc(alloc)
, _hash(hash) , _hash(hash)
, _size(0) {} , _size(0)
, _load(default_load) {
}
constexpr set(const set& set) constexpr set(const set& set)
: _alloc(set._alloc) : _alloc(set._alloc)
, _hash(set._hash) , _hash(set._hash)
, _size(set._size) { , _size(set._size)
, _load(default_load) {
} }
constexpr set(set&& set) noexcept constexpr set(set&& set) noexcept
@@ -127,7 +141,7 @@ public:
} }
constexpr void insert(elem_t&& val) { constexpr void insert(elem_t&& val) {
if (_size >= capacity()) { // expand when full if (_size == 0 or double(_size) / capacity() >= _load) { // expand when full
_expand(); _expand();
} }
@@ -135,7 +149,7 @@ public:
size_t i = _hash(value) % capacity(); // Initial search index size_t i = _hash(value) % capacity(); // Initial search index
int psl = 0; int psl = 0;
while (_alloc[i].value) { // Search for empty cell while (_alloc[i].value) { // Search for empty cell
if (*_alloc[i].value == val) { // Check to see if this element is already inserted if (_equal(*_alloc[i].value, val)) { // Check to see if this element is already inserted
return; return;
} }
if (psl >= _alloc[i].psl) { // When psl is higher, swap if (psl >= _alloc[i].psl) { // When psl is higher, swap
@@ -165,8 +179,8 @@ public:
int psl = 0; int psl = 0;
// Loop while there is a value and its psl is greater than our probe // Loop while there is a value and its psl is greater than our probe
while (_alloc[i].value && _alloc[i].psl > psl) { while (_alloc[i].value && _alloc[i].psl <= psl) {
if (*_alloc[i].value == val) { if (_equal(*_alloc[i].value, val)) {
return iterator(this, i); return iterator(this, i);
} }
i = (i + 1) % capacity(); ++psl; i = (i + 1) % capacity(); ++psl;
@@ -175,6 +189,20 @@ public:
return iterator(this, npos); return iterator(this, npos);
} }
constexpr elem_t* at(const iterator& it) {
size_t i = it._i;
if (i >= capacity()) return nullptr;
if (not _alloc[i].value) return nullptr;
return &*_alloc[i].value;
}
constexpr const elem_t* at(const iterator& it) const {
size_t i = it._i;
if (i >= capacity()) return nullopt;
if (not _alloc[i].value) return nullopt;
return &*_alloc[i].value;
}
constexpr bool contains(const elem_t& val) const { constexpr bool contains(const elem_t& val) const {
return this->find(val) != end(); return this->find(val) != end();
} }
@@ -251,6 +279,7 @@ public:
private: private:
const set* _set; const set* _set;
size_t _i; size_t _i;
friend set;
}; };
constexpr iterator begin() const { constexpr iterator begin() const {
@@ -271,10 +300,9 @@ public:
private: private:
constexpr void _expand() { constexpr void _expand() {
set cpy; // Create a new set set cpy; // Create a new set
cpy._alloc.allocate( cpy._alloc.callocate(
fennec::next_prime2(_alloc.capacity()) fennec::next_prime2(_alloc.capacity())
); );
fennec::memset(cpy._alloc.data(), 0, cpy._alloc.size());
// rehash // rehash
for (size_t i = 0; i < capacity(); ++i) { for (size_t i = 0; i < capacity(); ++i) {
@@ -289,7 +317,9 @@ private:
allocation<node, alloc_t> _alloc; allocation<node, alloc_t> _alloc;
hash_t _hash; hash_t _hash;
equal_t _equal;
size_t _size; size_t _size;
double _load;
}; };
} }

View File

@@ -0,0 +1,64 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_CONTAINERS_TUPLE_H
#define FENNEC_CONTAINERS_TUPLE_H
#include <fennec/containers/detail/__tuple.h>
#include <fennec/lang/type_sequences.h>
namespace fennec
{
// TODO: Document
template<typename...TypesT> struct tuple;
template<size_t i, typename...TypesT>
typename tuple<TypesT...>::template elem_t<i>& get(tuple<TypesT...>& x) {
using elem_t = typename tuple<TypesT...>::template elem_t<i>;
auto it = static_cast<detail::__tuple_leaf<i, elem_t>>(x);
return it;
}
template<size_t i, typename...TypesT>
const typename tuple<TypesT...>::template elem_t<i>& get(tuple<TypesT...>& x) {
using elem_t = typename tuple<TypesT...>::template elem_t<i>;
auto& it = static_cast<detail::__tuple_leaf<i, elem_t>>(x);
return it;
}
template<typename...TypesT>
struct tuple : detail::__tuple<make_index_sequence<sizeof...(TypesT)>, TypesT...> {
public:
using base_t = detail::__tuple<make_index_sequence<sizeof...(TypesT)>, TypesT...>;
template<size_t i>
using elem_t = nth_element<i, TypesT...>;
template<typename...ArgsT>
tuple(ArgsT&&...args) : base_t(args...) {
}
};
}
#endif // FENNEC_CONTAINERS_TUPLE_H

View File

@@ -25,6 +25,7 @@
#include <fennec/lang/assert.h> #include <fennec/lang/assert.h>
#include <fennec/math/common.h> #include <fennec/math/common.h>
#include <fennec/memory/bytes.h>
namespace fennec namespace fennec
{ {
@@ -303,6 +304,13 @@ private:
bool _const; bool _const;
}; };
template<>
struct hash<cstring> : hash<byte_array> {
constexpr size_t operator()(const cstring& str) {
return hash<byte_array>::operator()(byte_array(*str, str.size()));
}
};
} }
#endif // FENNEC_FPROC_STRINGS_CSTRING_H #endif // FENNEC_FPROC_STRINGS_CSTRING_H

View File

@@ -154,7 +154,7 @@ public:
/// \param i the index to access /// \param i the index to access
/// \returns a copy of the character /// \returns a copy of the character
constexpr char operator[](int i) const { constexpr char operator[](int i) const {
assertd(i >= 0 && i < size(), "Array Out of Bounds"); assertd(i >= 0 && (size_t)i < size(), "Array Out of Bounds");
return _str[i]; return _str[i];
} }
@@ -431,6 +431,13 @@ private:
alloc_t _str; alloc_t _str;
}; };
template<>
struct hash<string> : hash<byte_array> {
constexpr size_t operator()(const string& str) const {
return hash<byte_array>::operator()(byte_array(*str, str.size()));
}
};
} }

View File

@@ -0,0 +1,123 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_LANG_COMPARE_H
#define FENNEC_LANG_COMPARE_H
#include <fennec/lang/type_operators.h>
namespace fennec
{
// equality ============================================================================================================
template<typename T0, typename T1 = T0> struct equality;
template<typename T0, typename T1> requires has_equals_v<T0, T1>
struct equality<T0, T1> {
constexpr bool operator()(const T0& x, const T1& y) const {
return x == y;
}
};
template<typename T0, typename T1> requires(not has_equals_v<T0, T1>
and has_less_v<T0, T1> and has_less_v<T1, T0>)
struct equality<T0, T1> {
constexpr bool operator()(const T0& x, const T1& y) const {
return not(x < y) and not(y < x);
}
};
template<typename T0, typename T1> requires(not(has_equals_v<T0, T1>)
and(not has_less_v<T0, T1> or not has_less_v<T1, T0>)
and(has_greater_v<T0, T1> and has_greater_v<T1, T0>))
struct equality<T0, T1> {
constexpr bool operator()(const T0& x, const T1& y) const {
return not(x > y) and not(y > x);
}
};
// inequality ==========================================================================================================
template<typename T0, typename T1 = T0> struct inequality;
template<typename T0, typename T1> requires has_nequals_v<T0, T1>
struct inequality<T0, T1> {
constexpr bool operator()(const T0& x, const T1& y) const {
return x != y;
}
};
template<typename T0, typename T1> requires has_less_v<T0, T1> and has_less_v<T1, T0>
struct inequality<T0, T1> {
constexpr bool operator()(const T0& x, const T1& y) const {
return (x < y) or (y < x);
}
};
template<typename T0, typename T1> requires has_greater_v<T0, T1> and has_greater_v<T1, T0>
struct inequality<T0, T1> {
constexpr bool operator()(const T0& x, const T1& y) const {
return (x > y) or (y > x);
}
};
// less ================================================================================================================
template<typename T0, typename T1 = T0> requires has_less_v<T0, T1>
struct less {
constexpr bool operator()(const T0& x, const T1& y) const {
return x < y;
}
};
// less_equal ==========================================================================================================
template<typename T0, typename T1 = T0> requires has_less_equals_v<T0, T1>
struct less_equals {
constexpr bool operator()(const T0& x, const T1& y) const {
return x <= y;
}
};
// less ================================================================================================================
template<typename T0, typename T1 = T0> requires has_greater_v<T0, T1>
struct greater {
constexpr bool operator()(const T0& x, const T1& y) const {
return x < y;
}
};
// less_equal ==========================================================================================================
template<typename T0, typename T1 = T0> requires has_greater_equals_v<T0, T1>
struct greater_equals {
constexpr bool operator()(const T0& x, const T1& y) const {
return x <= y;
}
};
}
#endif // FENNEC_LANG_COMPARE_H

View File

@@ -21,123 +21,118 @@
#include <fennec/lang/types.h> #include <fennec/lang/types.h>
namespace fennec namespace fennec::detail
{ {
namespace detail // helper for bitwise and for 1 byte
{ constexpr size_t __bit_and_8(void* dst, const void* src) {
*static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) & *static_cast<const uint8_t*>(src); return 1;
// helper for bitwise and for 1 byte
constexpr size_t __bit_and_8(void* dst, const void* src) {
*static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) & *static_cast<const uint8_t*>(src); return 1;
}
// helper for bitwise and 2 bytes at once
constexpr size_t __bit_and_16(void* dst, const void* src) {
*static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) & *static_cast<const uint16_t*>(src); return 2;
}
// helper for bitwise and 4 bytes at once
constexpr size_t __bit_and_32(void* dst, const void* src) {
*static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) & *static_cast<const uint32_t*>(src); return 4;
}
// helper for bitwise and 8 bytes at once
constexpr size_t __bit_and_64(void* dst, const void* src) {
*static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) & *static_cast<const uint64_t*>(src); return 8;
}
// helper for selecting size
constexpr size_t __bit_and(void* dst, const void* src, size_t n) {
switch (n) {
case 0:
return 0;
case 1:
return __bit_and_8(dst, src);
case 2: case 3:
return __bit_and_16(dst, src);
case 4: case 5: case 6: case 7:
return __bit_and_32(dst, src);
default:
return __bit_and_64(dst, src);
} }
}
// helper for bitwise and 2 bytes at once
// helper for bitwise or for 1 byte constexpr size_t __bit_and_16(void* dst, const void* src) {
constexpr size_t __bit_or_8(void* dst, const void* src) { *static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) & *static_cast<const uint16_t*>(src); return 2;
*static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) | *static_cast<const uint8_t*>(src); return 1;
}
// helper for bitwise or 2 bytes at once
constexpr size_t __bit_or_16(void* dst, const void* src) {
*static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) | *static_cast<const uint16_t*>(src); return 2;
}
// helper for bitwise or 4 bytes at once
constexpr size_t __bit_or_32(void* dst, const void* src) {
*static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) | *static_cast<const uint32_t*>(src); return 4;
}
// helper for bitwise or 8 bytes at once
constexpr size_t __bit_or_64(void* dst, const void* src) {
*static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) | *static_cast<const uint64_t*>(src); return 8;
}
// helper for selecting size
constexpr size_t __bit_or(void* dst, const void* src, size_t n) {
switch (n) {
case 0:
return 0;
case 1:
return __bit_or_8(dst, src);
case 2: case 3:
return __bit_or_16(dst, src);
case 4: case 5: case 6: case 7:
return __bit_or_32(dst, src);
default:
return __bit_or_64(dst, src);
} }
}
// helper for bitwise and 4 bytes at once
// helper for bitwise and 1 byte constexpr size_t __bit_and_32(void* dst, const void* src) {
constexpr size_t __bit_xor_8(void* dst, const void* src) { *static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) & *static_cast<const uint32_t*>(src); return 4;
*static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) ^ *static_cast<const uint8_t*>(src); return 1;
}
// helper for bitwise xor 2 bytes at once
constexpr size_t __bit_xor_16(void* dst, const void* src) {
*static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) ^ *static_cast<const uint16_t*>(src); return 2;
}
// helper for bitwise xor 4 bytes at once
constexpr size_t __bit_xor_32(void* dst, const void* src) {
*static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) ^ *static_cast<const uint32_t*>(src); return 4;
}
// helper for bitwise xor 8 bytes at once
constexpr size_t __bit_xor_64(void* dst, const void* src) {
*static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) ^ *static_cast<const uint64_t*>(src); return 8;
}
// helper for selecting size
constexpr size_t __bit_xor(void* dst, const void* src, size_t n) {
switch (n) {
case 0:
return 0;
case 1:
return __bit_xor_8(dst, src);
case 2: case 3:
return __bit_xor_16(dst, src);
case 4: case 5: case 6: case 7:
return __bit_xor_32(dst, src);
default:
return __bit_xor_64(dst, src);
} }
}
} // helper for bitwise and 8 bytes at once
constexpr size_t __bit_and_64(void* dst, const void* src) {
*static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) & *static_cast<const uint64_t*>(src); return 8;
}
// helper for selecting size
constexpr size_t __bit_and(void* dst, const void* src, size_t n) {
switch (n) {
case 0:
return 0;
case 1:
return __bit_and_8(dst, src);
case 2: case 3:
return __bit_and_16(dst, src);
case 4: case 5: case 6: case 7:
return __bit_and_32(dst, src);
default:
return __bit_and_64(dst, src);
}
}
// helper for bitwise or for 1 byte
constexpr size_t __bit_or_8(void* dst, const void* src) {
*static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) | *static_cast<const uint8_t*>(src); return 1;
}
// helper for bitwise or 2 bytes at once
constexpr size_t __bit_or_16(void* dst, const void* src) {
*static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) | *static_cast<const uint16_t*>(src); return 2;
}
// helper for bitwise or 4 bytes at once
constexpr size_t __bit_or_32(void* dst, const void* src) {
*static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) | *static_cast<const uint32_t*>(src); return 4;
}
// helper for bitwise or 8 bytes at once
constexpr size_t __bit_or_64(void* dst, const void* src) {
*static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) | *static_cast<const uint64_t*>(src); return 8;
}
// helper for selecting size
constexpr size_t __bit_or(void* dst, const void* src, size_t n) {
switch (n) {
case 0:
return 0;
case 1:
return __bit_or_8(dst, src);
case 2: case 3:
return __bit_or_16(dst, src);
case 4: case 5: case 6: case 7:
return __bit_or_32(dst, src);
default:
return __bit_or_64(dst, src);
}
}
// helper for bitwise and 1 byte
constexpr size_t __bit_xor_8(void* dst, const void* src) {
*static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) ^ *static_cast<const uint8_t*>(src); return 1;
}
// helper for bitwise xor 2 bytes at once
constexpr size_t __bit_xor_16(void* dst, const void* src) {
*static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) ^ *static_cast<const uint16_t*>(src); return 2;
}
// helper for bitwise xor 4 bytes at once
constexpr size_t __bit_xor_32(void* dst, const void* src) {
*static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) ^ *static_cast<const uint32_t*>(src); return 4;
}
// helper for bitwise xor 8 bytes at once
constexpr size_t __bit_xor_64(void* dst, const void* src) {
*static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) ^ *static_cast<const uint64_t*>(src); return 8;
}
// helper for selecting size
constexpr size_t __bit_xor(void* dst, const void* src, size_t n) {
switch (n) {
case 0:
return 0;
case 1:
return __bit_xor_8(dst, src);
case 2: case 3:
return __bit_xor_16(dst, src);
case 4: case 5: case 6: case 7:
return __bit_xor_32(dst, src);
default:
return __bit_xor_64(dst, src);
}
}
} }

View File

@@ -22,42 +22,37 @@
#include <fennec/lang/types.h> #include <fennec/lang/types.h>
#include <fennec/lang/type_transforms.h> #include <fennec/lang/type_transforms.h>
namespace fennec namespace fennec::detail
{ {
namespace detail template<typename> struct __make_unsigned : type_identity<undefined_t> {};
{
template<typename> struct __make_unsigned : type_identity<undefined_t> {}; template<> struct __make_unsigned<char_t> : type_identity<uchar_t> {};
template<> struct __make_unsigned<uchar_t> : type_identity<uchar_t> {};
template<> struct __make_unsigned<char_t> : type_identity<uchar_t> {}; template<> struct __make_unsigned<schar_t> : type_identity<uchar_t> {};
template<> struct __make_unsigned<uchar_t> : type_identity<uchar_t> {}; template<> struct __make_unsigned<short_t> : type_identity<ushort_t> {};
template<> struct __make_unsigned<schar_t> : type_identity<uchar_t> {}; template<> struct __make_unsigned<ushort_t> : type_identity<ushort_t> {};
template<> struct __make_unsigned<short_t> : type_identity<ushort_t> {}; template<> struct __make_unsigned<uint_t> : type_identity<uint_t> {};
template<> struct __make_unsigned<ushort_t> : type_identity<ushort_t> {}; template<> struct __make_unsigned<int_t> : type_identity<uint_t> {};
template<> struct __make_unsigned<uint_t> : type_identity<uint_t> {}; template<> struct __make_unsigned<long_t> : type_identity<ulong_t> {};
template<> struct __make_unsigned<int_t> : type_identity<uint_t> {}; template<> struct __make_unsigned<ulong_t> : type_identity<ulong_t> {};
template<> struct __make_unsigned<long_t> : type_identity<ulong_t> {}; template<> struct __make_unsigned<llong_t> : type_identity<ullong_t> {};
template<> struct __make_unsigned<ulong_t> : type_identity<ulong_t> {}; template<> struct __make_unsigned<ullong_t> : type_identity<ullong_t> {};
template<> struct __make_unsigned<llong_t> : type_identity<ullong_t> {};
template<> struct __make_unsigned<ullong_t> : type_identity<ullong_t> {};
template<typename> struct __make_signed : type_identity<undefined_t> {}; template<typename> struct __make_signed : type_identity<undefined_t> {};
template<> struct __make_signed<char_t> : type_identity<schar_t> {}; template<> struct __make_signed<char_t> : type_identity<schar_t> {};
template<> struct __make_signed<uchar_t> : type_identity<schar_t> {}; template<> struct __make_signed<uchar_t> : type_identity<schar_t> {};
template<> struct __make_signed<schar_t> : type_identity<schar_t> {}; template<> struct __make_signed<schar_t> : type_identity<schar_t> {};
template<> struct __make_signed<short_t> : type_identity<short_t> {}; template<> struct __make_signed<short_t> : type_identity<short_t> {};
template<> struct __make_signed<ushort_t> : type_identity<short_t> {}; template<> struct __make_signed<ushort_t> : type_identity<short_t> {};
template<> struct __make_signed<uint_t> : type_identity<int_t> {}; template<> struct __make_signed<uint_t> : type_identity<int_t> {};
template<> struct __make_signed<int_t> : type_identity<int_t> {}; template<> struct __make_signed<int_t> : type_identity<int_t> {};
template<> struct __make_signed<long_t> : type_identity<long_t> {}; template<> struct __make_signed<long_t> : type_identity<long_t> {};
template<> struct __make_signed<ulong_t> : type_identity<long_t> {}; template<> struct __make_signed<ulong_t> : type_identity<long_t> {};
template<> struct __make_signed<llong_t> : type_identity<llong_t> {}; template<> struct __make_signed<llong_t> : type_identity<llong_t> {};
template<> struct __make_signed<ullong_t> : type_identity<llong_t> {}; template<> struct __make_signed<ullong_t> : type_identity<llong_t> {};
}
} }

View File

@@ -21,16 +21,20 @@
#include <fennec/lang/type_transforms.h> #include <fennec/lang/type_transforms.h>
namespace fennec namespace fennec::detail
{ {
namespace detail template<typename FirstT, typename... RestT> struct __first_element : type_identity<FirstT> {};
{
template<typename FirstT, typename... RestT> struct __first_element : type_identity<FirstT>{}; template<size_t n, size_t i, typename...TypesT> struct __nth_element;
} template<size_t n, size_t i> struct __nth_element<n, i> : type_identity<void> {};
template<size_t n, size_t i, typename HeadT, typename...RestT>
struct __nth_element<n, i, HeadT, RestT...> : conditional<
n == i, type_identity<HeadT>,
__nth_element<n, i + 1, RestT...>
> {};
} }
#endif // FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H #endif // FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H

View File

@@ -22,53 +22,53 @@
#include <fennec/lang/constants.h> #include <fennec/lang/constants.h>
#include <fennec/lang/float.h> #include <fennec/lang/float.h>
namespace fennec namespace fennec::detail
{ {
namespace detail // Nothing interesting to note here
{ template<typename> struct __is_void : false_type {};
template<> struct __is_void<void> : true_type {};
// Nothing interesting to note here template<typename> struct __is_bool : false_type {};
template<typename> struct __is_void : false_type {}; template<> struct __is_bool<bool_t> : true_type {};
template<> struct __is_void<void> : true_type {};
template<typename> struct __is_bool : false_type {}; template<typename> struct __is_null_pointer : false_type {};
template<> struct __is_bool<bool_t> : true_type {}; template<> struct __is_null_pointer<nullptr_t> : true_type {};
template<typename> struct __is_null_pointer : false_type {}; // Provides definitions for all builtin int types
template<> struct __is_null_pointer<nullptr_t> : true_type {}; template<typename> struct __is_integral : false_type {};
template<> struct __is_integral<bool_t> : true_type {};
template<> struct __is_integral<char_t> : true_type {};
template<> struct __is_integral<char8_t> : true_type {};
template<> struct __is_integral<char16_t> : true_type {};
template<> struct __is_integral<char32_t> : true_type {};
template<> struct __is_integral<schar_t> : true_type {};
template<> struct __is_integral<uchar_t> : true_type {};
template<> struct __is_integral<wchar_t> : true_type {};
template<> struct __is_integral<short_t> : true_type {};
template<> struct __is_integral<ushort_t> : true_type {};
template<> struct __is_integral<int_t> : true_type {};
template<> struct __is_integral<uint_t> : true_type {};
template<> struct __is_integral<long_t> : true_type {};
template<> struct __is_integral<ulong_t> : true_type {};
template<> struct __is_integral<llong_t> : true_type {};
template<> struct __is_integral<ullong_t> : true_type {};
// Provides definitions for all builtin int types // Most unsigned types will underflow `-1` to the types maximum value
template<typename> struct __is_integral : false_type {}; template<typename TypeT> struct __is_signed : bool_constant<TypeT(-1) < TypeT(0)> {};
template<> struct __is_integral<bool_t> : true_type {}; template<typename TypeT> struct __is_unsigned : bool_constant<TypeT(-1) >= TypeT(0)> {};
template<> struct __is_integral<char_t> : true_type {};
template<> struct __is_integral<char8_t> : true_type {};
template<> struct __is_integral<char16_t> : true_type {};
template<> struct __is_integral<char32_t> : true_type {};
template<> struct __is_integral<schar_t> : true_type {};
template<> struct __is_integral<uchar_t> : true_type {};
template<> struct __is_integral<wchar_t> : true_type {};
template<> struct __is_integral<short_t> : true_type {};
template<> struct __is_integral<ushort_t> : true_type {};
template<> struct __is_integral<int_t> : true_type {};
template<> struct __is_integral<uint_t> : true_type {};
template<> struct __is_integral<long_t> : true_type {};
template<> struct __is_integral<ulong_t> : true_type {};
template<> struct __is_integral<llong_t> : true_type {};
template<> struct __is_integral<ullong_t> : true_type {};
// Most unsigned types will underflow `-1` to the types maximum value template<typename> struct __is_floating_point : false_type {};
template<typename TypeT> struct __is_signed : bool_constant<TypeT(-1) < TypeT(0)> {}; template<> struct __is_floating_point<float_t> : true_type {};
template<typename TypeT> struct __is_unsigned : bool_constant<TypeT(-1) >= TypeT(0)> {}; template<> struct __is_floating_point<double_t> : true_type {};
template<typename> struct __is_floating_point : false_type {}; template<typename> struct __is_pointer : false_type {};
template<> struct __is_floating_point<float_t> : true_type {}; template<typename T> struct __is_pointer<T*> : true_type {};
template<> struct __is_floating_point<double_t> : true_type {};
template<typename> struct __is_pointer : false_type {}; template<typename T, typename U = T&&> U __declval(int);
template<typename T> struct __is_pointer<T*> : true_type {}; template<typename T> T __declval(long);
} template<typename T> struct __declval_protector : bool_constant<false> {};
} }

View File

@@ -21,34 +21,29 @@
#include <fennec/lang/types.h> #include <fennec/lang/types.h>
namespace fennec namespace fennec::detail
{ {
namespace detail template<typename _Tp, typename = void>
{ struct __add_lvalue_reference {
using type = _Tp;
};
template<typename _Tp, typename = void> template<typename _Tp>
struct __add_lvalue_reference { struct __add_lvalue_reference<_Tp, void_t<_Tp&>> {
using type = _Tp; using type = _Tp&;
}; };
template<typename _Tp>
struct __add_lvalue_reference<_Tp, void_t<_Tp&>> {
using type = _Tp&;
};
template<typename _Tp, typename = void> template<typename _Tp, typename = void>
struct __add_rvalue_reference { struct __add_rvalue_reference {
using type = _Tp; using type = _Tp;
}; };
template<typename _Tp> template<typename _Tp>
struct __add_rvalue_reference<_Tp, void_t<_Tp&&>> { struct __add_rvalue_reference<_Tp, void_t<_Tp&&>> {
using type = _Tp&&; using type = _Tp&&;
}; };
}
} }

View File

@@ -0,0 +1,112 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_LANG_TYPE_OPERATORS_H
#define FENNEC_LANG_TYPE_OPERATORS_H
namespace fennec
{
// https://stackoverflow.com/questions/6534041/how-to-check-whether-operator-exists
// has_equals ==========================================================================================================
template<typename T0, typename T1 = T0>
struct has_equals {
// Use SFINAE to check for the operator
template<typename U, typename V> static auto test(U*) -> decltype(declval<U>() == declval<V>());
template<typename, typename> static auto test(...) -> false_type;
static constexpr bool value = is_same_v<bool, decltype(test<T0, T1>(0))>;
};
template<typename T0, typename T1 = T0> constexpr bool has_equals_v = has_equals<T0, T1>::value;
// has_nequals =========================================================================================================
template<typename T0, typename T1 = T0>
struct has_nequals {
// Use SFINAE to check for the operator
template<typename U, typename V> static auto test(U*) -> decltype(declval<U>() != declval<V>());
template<typename, typename> static auto test(...) -> false_type;
static constexpr bool value = is_same_v<bool, decltype(test<T0, T1>(0))>;
};
template<typename T0, typename T1 = T0> constexpr bool has_nequals_v = has_nequals<T0, T1>::value;
// has_less ============================================================================================================
template<typename T0, typename T1 = T0>
struct has_less {
// Use SFINAE to check for the operator
template<typename U, typename V> static auto test(U*) -> decltype(declval<U>() < declval<V>());
template<typename, typename> static auto test(...) -> false_type;
static constexpr bool value = is_same_v<bool, decltype(test<T0, T1>(0))>;
};
template<typename T0, typename T1 = T0> constexpr bool has_less_v = has_less<T0, T1>::value;
// has_less_equals =====================================================================================================
template<typename T0, typename T1 = T0>
struct has_less_equals {
// Use SFINAE to check for the operator
template<typename U, typename V> static auto test(U*) -> decltype(declval<U>() <= declval<V>());
template<typename, typename> static auto test(...) -> false_type;
static constexpr bool value = is_same_v<bool, decltype(test<T0, T1>(0))>;
};
template<typename T0, typename T1 = T0> constexpr bool has_less_equals_v = has_less_equals<T0, T1>::value;
// has_greater =========================================================================================================
template<typename T0, typename T1 = T0>
struct has_greater {
// Use SFINAE to check for the operator
template<typename U, typename V> static auto test(U*) -> decltype(declval<U>() > declval<V>());
template<typename, typename> static auto test(...) -> false_type;
static constexpr bool value = is_same_v<bool, decltype(test<T0, T1>(0))>;
};
template<typename T0, typename T1 = T0> constexpr bool has_greater_v = has_greater<T0, T1>::value;
// has_greater_equals ==================================================================================================
template<typename T0, typename T1 = T0>
struct has_greater_equals {
// Use SFINAE to check for the operator
template<typename U, typename V> static auto test(U*) -> decltype(declval<U>() >= declval<V>());
template<typename, typename> static auto test(...) -> false_type;
static constexpr bool value = is_same_v<bool, decltype(test<T0, T1>(0))>;
};
template<typename T0, typename T1 = T0> constexpr bool has_greater_equals_v = has_greater_equals<T0, T1>::value;
}
#endif // FENNEC_LANG_TYPE_OPERATORS_H

View File

@@ -69,6 +69,8 @@ template<typename...TypesT> struct first_element : detail::__first_element<Types
template<typename...TypesT> using first_element_t = typename first_element<TypesT...>::type; template<typename...TypesT> using first_element_t = typename first_element<TypesT...>::type;
template<size_t n, typename...TypesT> struct nth_element : detail::__nth_element<n, 0, TypesT...> {};
/// ///
/// \brief Take a Template with a Pack `ClassT<ArgsT...>` and replace the first `ArgT` of `ArgsT...` with `SubT` /// \brief Take a Template with a Pack `ClassT<ArgsT...>` and replace the first `ArgT` of `ArgsT...` with `SubT`

View File

@@ -112,6 +112,14 @@
namespace fennec namespace fennec
{ {
// fennec::declval =====================================================================================================
template<typename T> auto declval() noexcept -> decltype(detail::__declval<T>(0)) {
static_assert(detail::__declval_protector<T>{}, "declval must not be used");
return detail::__declval<T>(0);
}
// fennec::is_void ===================================================================================================== // fennec::is_void =====================================================================================================
/// ///

View File

@@ -20,32 +20,29 @@
#ifndef FENNEC_MATH_SWIZZLE_STORAGE_H #ifndef FENNEC_MATH_SWIZZLE_STORAGE_H
#define FENNEC_MATH_SWIZZLE_STORAGE_H #define FENNEC_MATH_SWIZZLE_STORAGE_H
namespace fennec namespace fennec::detail
{ {
namespace detail //
{ // \brief Backing storage struct for \ref fennec::swizzle "swizzle"
// \tparam DataT Data Type
/// // \tparam ScalarT Element Types
/// \brief Backing storage struct for \ref fennec::swizzle "swizzle" // \tparam IndicesV Swizzle Order
/// \tparam DataT Data Type
/// \tparam ScalarT Element Types
/// \tparam IndicesV Swizzle Order
template<typename DataT, typename ScalarT, size_t...IndicesV> template<typename DataT, typename ScalarT, size_t...IndicesV>
struct swizzle_storage struct swizzle_storage
{ {
/// //
/// \brief an array containing the indices of this swizzle // \brief an array containing the indices of this swizzle
inline static constexpr size_t indices[] = { IndicesV... }; inline static constexpr size_t indices[] = { IndicesV... };
/// //
/// \brief an array containing the scalar values of this swizzle // \brief an array containing the scalar values of this swizzle
DataT data; DataT data;
/// //
/// \brief element access, returns a copy of the value at index \p i // \brief element access, returns a copy of the value at index \p i
/// \param i the index // \param i the index
/// \returns a copy of the scalar value at index \p i // \returns a copy of the scalar value at index \p i
constexpr ScalarT operator[](size_t i) const noexcept { constexpr ScalarT operator[](size_t i) const noexcept {
return data[indices[i]]; return data[indices[i]];
} }
@@ -53,7 +50,5 @@ struct swizzle_storage
} }
}
#endif // FENNEC_MATH_SWIZZLE_STORAGE_H #endif // FENNEC_MATH_SWIZZLE_STORAGE_H

View File

@@ -27,65 +27,60 @@
#include <fennec/containers/array.h> #include <fennec/containers/array.h>
namespace fennec namespace fennec::detail
{ {
namespace detail //
{ // \brief helper class for generating vectors
// \tparam scalar base scalar type
/// // \tparam size size of the vector type
/// \brief helper class for generating vectors
/// \tparam scalar base scalar type
/// \tparam size size of the vector type
template<typename scalar, size_t size> template<typename scalar, size_t size>
struct vector_base_type_helper struct vector_base_type_helper
{ {
/// //
/// \var SizeV // \var SizeV
/// \brief size of the vector type // \brief size of the vector type
inline static constexpr size_t SizeV = size; inline static constexpr size_t SizeV = size;
/// //
/// \brief Base scalar type // \brief Base scalar type
using ScalarT = scalar; using ScalarT = scalar;
/// //
/// \brief Base vector type // \brief Base vector type
using VectorT = vec<ScalarT, SizeV>; using VectorT = vec<ScalarT, SizeV>;
/// //
/// \brief Backing array holding the elements // \brief Backing array holding the elements
using DataT = array<ScalarT, SizeV>; using DataT = array<ScalarT, SizeV>;
/// //
/// \brief Helper for generating a swizzle from a set of indices // \brief Helper for generating a swizzle from a set of indices
/// \tparam IndicesV Indices of the vector to pull from // \tparam IndicesV Indices of the vector to pull from
template<size_t...IndicesV> struct SwizzleGen template<size_t...IndicesV> struct SwizzleGen
{ {
/// \brief generated swizzle type // \brief generated swizzle type
using type = swizzle<VectorT, DataT, ScalarT, IndicesV...>; using type = swizzle<VectorT, DataT, ScalarT, IndicesV...>;
}; };
// Specialization for single component swizzles to decay into a scalar // Specialization for single component swizzles to decay into a scalar
template<size_t IndexV> struct SwizzleGen<IndexV> template<size_t IndexV> struct SwizzleGen<IndexV>
{ {
/// \brief decayed scalar type // \brief decayed scalar type
using type = ScalarT; using type = ScalarT;
}; };
/// //
/// \brief backing storage type // \brief backing storage type
using StorageT = vector_storage<SizeV, SwizzleGen, DataT>; using StorageT = vector_storage<SizeV, SwizzleGen, DataT>;
}; };
/// //
/// \brief helper for getting the storage type of the vector constructed with the provided size and scalar type // \brief helper for getting the storage type of the vector constructed with the provided size and scalar type
template<typename ScalarT, size_t SizeV> template<typename ScalarT, size_t SizeV>
using vector_base_type = typename vector_base_type_helper<ScalarT, SizeV>::StorageT; using vector_base_type = typename vector_base_type_helper<ScalarT, SizeV>::StorageT;
} }
}
#endif // FENNEC_MATH_VECTOR_BASE_H #endif // FENNEC_MATH_VECTOR_BASE_H

File diff suppressed because it is too large Load Diff

View File

@@ -467,7 +467,7 @@ public:
} }
// Allocation and Deallocation ========================================================================================= // Allocation and Deallocation =====================================================================================
/// ///
/// \brief Allocate a block of memory for the allocation. /// \brief Allocate a block of memory for the allocation.
@@ -483,6 +483,21 @@ public:
} }
} }
///
/// \brief Allocate a block of memory for the allocation.
/// If there is already an allocated block of memory, the previous allocation is released.
/// \param n The number of elements of type `T` to allocate for
constexpr void callocate(size_t n, align_t align = zero<align_t>()) noexcept {
deallocate();
if (align != zero<align_t>()) {
_data = _alloc.allocate(_capacity = n, _alignment = align);
} else {
_data = _alloc.allocate(_capacity = n);
}
fennec::memset(static_cast<void*>(_data), 0, _capacity * sizeof(T));
}
/// ///
/// \brief Release the block of memory. /// \brief Release the block of memory.
constexpr void deallocate() noexcept { constexpr void deallocate() noexcept {

View File

@@ -92,7 +92,7 @@ public:
/// \returns a reference to the byte at `i` /// \returns a reference to the byte at `i`
constexpr byte_t& operator[](int i) { constexpr byte_t& operator[](int i) {
assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const"); assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
assertd(i < _size, "Array Out of Bounds"); assertd(i >= 0 && (size_t)i < _size, "Array Out of Bounds");
return _arr[i]; return _arr[i];
} }
@@ -102,7 +102,7 @@ public:
/// \returns a copy of the byte at `i` /// \returns a copy of the byte at `i`
constexpr byte_t operator[](int i) const { constexpr byte_t operator[](int i) const {
assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const"); assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
assertd(i < _size, "Array Out of Bounds"); assertd(i >= 0 && (size_t)i < _size, "Array Out of Bounds");
return _carr[i]; return _carr[i];
} }
@@ -123,7 +123,7 @@ public:
template<typename T> template<typename T>
constexpr const T* cast() const { constexpr const T* cast() const {
const void* temp = _carr; const void* temp = _carr;
return static_cast<T*>(temp); return static_cast<const T*>(temp);
} }
private: private:
@@ -139,7 +139,7 @@ private:
/// \brief Byte Array Hash Function /// \brief Byte Array Hash Function
template<> template<>
struct hash<byte_array> { struct hash<byte_array> {
size_t operator()(const byte_array& bytes) { size_t operator()(const byte_array& bytes) const {
// Murmur2 // Murmur2
static constexpr uint64_t m = 0xc6a4a7935bd1e995; static constexpr uint64_t m = 0xc6a4a7935bd1e995;
@@ -148,7 +148,7 @@ struct hash<byte_array> {
const uint64_t n = bytes.size(); const uint64_t n = bytes.size();
uint64_t h = s ^ (n * m); uint64_t h = s ^ (n * m);
const uint64_t* x = bytes.cast<>(); const uint64_t* x = bytes.cast<uint64_t>();
const uint64_t* y = x + (n / sizeof(uint64_t)); const uint64_t* y = x + (n / sizeof(uint64_t));
while (x != y) { while (x != y) {
@@ -164,15 +164,16 @@ struct hash<byte_array> {
const uint8_t* b = (const uint8_t*)x; const uint8_t* b = (const uint8_t*)x;
switch (n & 7) { switch (n & 7) {
case 7: h ^= uint64_t(b[6]) << 48; case 7: h ^= uint64_t(b[6]) << 48; __attribute__((fallthrough));
case 6: h ^= uint64_t(b[5]) << 40; case 6: h ^= uint64_t(b[5]) << 40; __attribute__((fallthrough));
case 5: h ^= uint64_t(b[4]) << 32; case 5: h ^= uint64_t(b[4]) << 32; __attribute__((fallthrough));
case 4: h ^= uint64_t(b[3]) << 24; case 4: h ^= uint64_t(b[3]) << 24; __attribute__((fallthrough));
case 3: h ^= uint64_t(b[2]) << 16; case 3: h ^= uint64_t(b[2]) << 16; __attribute__((fallthrough));
case 2: h ^= uint64_t(b[1]) << 8; case 2: h ^= uint64_t(b[1]) << 8; __attribute__((fallthrough));
case 1: h ^= uint64_t(b[0]); case 1: h ^= uint64_t(b[0]);
h *= m; h *= m;
default: default:
break;
} }
h ^= h >> r; h ^= h >> r;

View File

@@ -18,7 +18,7 @@
/// ///
/// \file memory.h /// \file memory.h
/// \brief \ref /// \brief \ref fennec_memory
/// ///
/// ///
/// \details /// \details
@@ -32,17 +32,9 @@
#define FENNEC_MEMORY_MEMORY_H #define FENNEC_MEMORY_MEMORY_H
/// ///
/// \page fennec_lang C++ Language Library /// \page fennec_memory Memory Management Library
/// ///
/// This library implements the parts of the C++ stdlib that relate to built-in types and metaprogramming. /// This library implements functions and data structures to memory management and manipulation
///
/// - \subpage fennec_lang_assert
/// - \subpage fennec_lang_bit_manipulation
/// - \subpage fennec_lang_intrinsics
/// - \subpage fennec_lang_limits
/// - \subpage fennec_lang_metaprogramming
/// - \subpage fennec_lang_types
/// - \subpage fennec_lang_utility
/// ///
/// ///

View File

@@ -921,7 +921,7 @@ bool file::eof() const {
char file::getc() { char file::getc() {
assert(_error == nullptr, "Attempted an Operation on a File in an Errored State"); assert(_error == nullptr, "Attempted an Operation on a File in an Errored State");
assert(not _mode & fmode_wide, "Attempted Byte Operation on Wide File"); assert(not(_mode & fmode_wide), "Attempted Byte Operation on Wide File");
// Check if there is a file // Check if there is a file
if (_handle == nullptr) { if (_handle == nullptr) {
@@ -961,7 +961,7 @@ size_t file::read(void* data, size_t size, size_t n) {
string file::getline() { string file::getline() {
assert(_error == nullptr, "Attempted an Operation on a File in an Errored State"); assert(_error == nullptr, "Attempted an Operation on a File in an Errored State");
assert(not _mode & fmode_wide, "Attempted Byte Operation on Wide File"); assert(not(_mode & fmode_wide), "Attempted Byte Operation on Wide File");
// Check if there is a file // Check if there is a file
if (_handle == nullptr) { if (_handle == nullptr) {
@@ -1011,7 +1011,7 @@ wstring file::getwline() {
bool file::putc(char c) { bool file::putc(char c) {
assert(_error == nullptr, "Attempted an Operation on a File in an Errored State"); assert(_error == nullptr, "Attempted an Operation on a File in an Errored State");
assert(not _mode & fmode_wide, "Attempted Byte Operation on Wide File"); assert(not(_mode & fmode_wide), "Attempted Byte Operation on Wide File");
// Check if there is a file // Check if there is a file
if (_handle == nullptr) { if (_handle == nullptr) {

View File

@@ -39,7 +39,7 @@ wayland_display::wayland_display(linux_platform* platform, const cstring& drv)
, _handle() , _handle()
, _platform(platform) { , _platform(platform) {
load_symbols(_platform); load_symbols(_platform);
_handle = wl_display_connect(nullptr); _handle = wl_display_connect(drv);
} }
wayland_display::~wayland_display() { wayland_display::~wayland_display() {

View File

@@ -33,6 +33,7 @@ add_executable(fennec-test main.cpp
tests/lang/test_hashing.h tests/lang/test_hashing.h
tests/containers/test_array.h tests/containers/test_array.h
tests/containers/test_set.h tests/containers/test_set.h
tests/containers/test_map.h
) )
target_compile_definitions(fennec-test PUBLIC FENNEC_TEST_CWD="${CMAKE_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME}" target_compile_definitions(fennec-test PUBLIC FENNEC_TEST_CWD="${CMAKE_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME}"

View File

@@ -23,26 +23,21 @@
#include <fennec/containers/array.h> #include <fennec/containers/array.h>
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_containers_array() {
{
inline void fennec_test_containers_array() { const char string[] = "Hello World!";
array<char, sizeof(string)> arr1;
array<char, sizeof(string)> arr2;
strcpy(&arr1[0], string);
strcpy(&arr2[0], string);
const char string[] = "Hello World!"; fennec_test_run(strcmp(&arr1[0], string), 0);
array<char, sizeof(string)> arr1; fennec_test_run(strcmp(&arr2[0], string), 0);
array<char, sizeof(string)> arr2; fennec_test_run(arr1 == arr2, true);
strcpy(&arr1[0], string); }
strcpy(&arr2[0], string);
fennec_test_run(strcmp(&arr1[0], string), 0);
fennec_test_run(strcmp(&arr2[0], string), 0);
fennec_test_run(arr1 == arr2, true);
}
}
} }

View File

@@ -23,33 +23,28 @@
#include <fennec/containers/dynarray.h> #include <fennec/containers/dynarray.h>
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_containers_dynarray() {
{
inline void fennec_test_containers_dynarray() { dynarray<int> test1;
dynarray<int> test2;
dynarray<int> test1; int n = 10000;
dynarray<int> test2; test1.resize(n); test2.resize(n);
for (int i = 0; i < n; ++i) {
test1.push_back(i);
test2.push_back(n - i - 1);
}
int n = 10000; for (int i = 0; i < n; ++i) {
test1.resize(n); test2.resize(n); assertf(test1[i] == test2[n - i - 1], "Failed dynarray::push_back");
for (int i = 0; i < n; ++i) { }
test1.push_back(i);
test2.push_back(n - i - 1); std::cout << "passed" << std::endl;
} }
for (int i = 0; i < n; ++i) {
assertf(test1[i] == test2[n - i - 1], "Failed dynarray::push_back");
}
std::cout << "passed" << std::endl;
}
}
} }
#endif // FENNEC_TEST_CONTAINERS_DYNARRAY_H #endif // FENNEC_TEST_CONTAINERS_DYNARRAY_H

View File

@@ -0,0 +1,41 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_TEST_CONTAINERS_MAP_H
#define FENNEC_TEST_CONTAINERS_MAP_H
#include <fennec/containers/map.h>
#include <fennec/fproc/strings/string.h>
namespace fennec::test {
inline void fennec_test_containers_map() {
map<string, string> map;
map.emplace("Hello", "World");
fennec_test_run(*map["Hello"], string("World"));
map.erase("Hello");
fennec_test_run(map["Hello"], static_cast<string*>(nullptr));
}
}
#endif // FENNEC_TEST_CONTAINERS_MAP_H

View File

@@ -23,102 +23,115 @@
#include <fennec/containers/optional.h> #include <fennec/containers/optional.h>
namespace fennec namespace fennec::test
{ {
namespace test enum opt_test_ : uint8_t {
{ opt_test_none = 0x1 << 0,
opt_test_default_constructor = 0x1 << 1,
opt_test_destructor = 0x1 << 2,
opt_test_copy_constructor = 0x1 << 3,
opt_test_move_constructor = 0x1 << 4,
opt_test_copy_assignment = 0x1 << 5,
opt_test_move_assignment = 0x1 << 6,
};
enum opt_test_ : uint8_t { struct optional_helper {
opt_test_none = 0x1 << 0,
opt_test_default_constructor = 0x1 << 1,
opt_test_destructor = 0x1 << 2,
opt_test_copy_constructor = 0x1 << 3,
opt_test_move_constructor = 0x1 << 4,
opt_test_copy_assignment = 0x1 << 5,
opt_test_move_assignment = 0x1 << 6,
};
struct optional_helper { inline static uint8_t test = opt_test_none;
inline static uint8_t test = opt_test_none; optional_helper() : i(0) {
fennec_test_run(bool(test & opt_test_default_constructor), true);
}
optional_helper() : i(0) { ~optional_helper() {
fennec_test_run(bool(test & opt_test_default_constructor), true); fennec_test_run(bool(test & opt_test_destructor), true);
}
optional_helper(const optional_helper&) : i(0) {
fennec_test_run(bool(test & opt_test_copy_constructor), true);
}
optional_helper(optional_helper&&) noexcept : i(0) {
fennec_test_run(bool(test & opt_test_move_constructor), true);
}
optional_helper& operator=(const optional_helper&) {
fennec_test_run(bool(test & opt_test_copy_assignment), true);
return *this;
}
optional_helper& operator=(optional_helper&&) noexcept {
fennec_test_run(bool(test & opt_test_move_assignment), true);
return *this;
}
int i;
};
inline void fennec_test_containers_optional() {
static_assert(
is_default_constructible_v<optional_helper>
and is_copy_constructible_v<optional_helper>
and is_move_constructible_v<optional_helper>
and is_copy_assignable_v<optional_helper>
and is_move_assignable_v<optional_helper>
);
optional<optional_helper> opt = optional<optional_helper>();
optional_helper::test = opt_test_default_constructor;
opt.emplace();
fennec_test_spacer(1);
optional_helper::test = opt_test_destructor;
opt.reset();
fennec_test_spacer(1);
optional_helper::test = opt_test_default_constructor | opt_test_copy_constructor | opt_test_destructor;
opt = copy(optional_helper());
fennec_test_spacer(1);
optional_helper::test = opt_test_destructor;
opt.reset();
fennec_test_spacer(1);
optional_helper::test = opt_test_default_constructor | opt_test_move_constructor | opt_test_destructor;
opt = optional_helper();
fennec_test_spacer(1);
optional_helper::test = opt_test_destructor;
opt.reset();
fennec_test_spacer(1);
optional_helper::test = opt_test_default_constructor;
opt.emplace();
fennec_test_spacer(1);
optional_helper::test = opt_test_default_constructor | opt_test_copy_assignment | opt_test_destructor;
opt = copy(optional_helper());
fennec_test_spacer(1);
optional_helper::test = opt_test_default_constructor | opt_test_move_assignment | opt_test_destructor;
opt = optional_helper();
fennec_test_spacer(1);
optional_helper::test = opt_test_destructor;
opt.reset();
std::cout << opt << std::endl;
std::cout << "passed" << std::endl;
} }
~optional_helper() {
fennec_test_run(bool(test & opt_test_destructor), true);
}
optional_helper(const optional_helper&) : i(0) {
fennec_test_run(bool(test & opt_test_copy_constructor), true);
}
optional_helper(optional_helper&&) noexcept : i(0) {
fennec_test_run(bool(test & opt_test_move_constructor), true);
}
optional_helper& operator=(const optional_helper&) {
fennec_test_run(bool(test & opt_test_copy_assignment), true);
return *this;
}
optional_helper& operator=(optional_helper&&) noexcept {
fennec_test_run(bool(test & opt_test_move_assignment), true);
return *this;
}
int i;
};
inline void fennec_test_containers_optional() {
static_assert(
is_default_constructible_v<optional_helper>
and is_copy_constructible_v<optional_helper>
and is_move_constructible_v<optional_helper>
and is_copy_assignable_v<optional_helper>
and is_move_assignable_v<optional_helper>
);
optional<optional_helper> opt = optional<optional_helper>();
optional_helper::test = opt_test_default_constructor;
opt.emplace();
optional_helper::test = opt_test_destructor;
opt.reset();
optional_helper::test = opt_test_default_constructor | opt_test_copy_constructor | opt_test_destructor;
opt = copy(optional_helper());
optional_helper::test = opt_test_destructor;
opt.reset();
optional_helper::test = opt_test_default_constructor | opt_test_move_constructor | opt_test_destructor;
opt = optional_helper();
optional_helper::test = opt_test_destructor;
opt.reset();
optional_helper::test = opt_test_default_constructor;
opt.emplace();
optional_helper::test = opt_test_default_constructor | opt_test_copy_assignment | opt_test_destructor;
opt = copy(optional_helper());
optional_helper::test = opt_test_default_constructor | opt_test_move_assignment | opt_test_destructor;
opt = optional_helper();
optional_helper::test = opt_test_destructor;
opt.reset();
std::cout << opt << std::endl;
std::cout << "passed" << std::endl;
}
}
} }
#endif // FENNEC_TEST_CONTAINERS_OPTIONAL_H #endif // FENNEC_TEST_CONTAINERS_OPTIONAL_H

View File

@@ -25,34 +25,29 @@
#include <unordered_set> #include <unordered_set>
#include <fennec/containers/set.h> #include <fennec/containers/set.h>
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_containers_set() {
{
inline void fennec_test_containers_set() { using type_t = decltype(rand());
std::unordered_set<type_t> ref;
set<type_t> test;
using type_t = decltype(rand()); srand(0);
std::unordered_set<type_t> ref; for (int i = 0; i < 10000; ++i) {
set<type_t> test; type_t v = rand();
ref.insert(v);
test.insert(v);
}
srand(0); for (int i = 0; i < 10000; ++i) {
for (int i = 0; i < 10000; ++i) { assertf(ref.contains(i) == test.contains(i), "set test failed");
type_t v = rand(); }
ref.insert(v);
test.insert(v); std::cout << "passed" << std::endl;
} }
for (int i = 0; i < 10000; ++i) {
assertf(ref.contains(i) == test.contains(i), "set test failed");
}
std::cout << "passed" << std::endl;
}
}
} }
#endif // FENNEC_TEST_CONTAINERS_SET_H #endif // FENNEC_TEST_CONTAINERS_SET_H

View File

@@ -21,35 +21,30 @@
#include <fennec/fproc/strings/cstring.h> #include <fennec/fproc/strings/cstring.h>
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_fproc_strings_cstring()
{ {
static char test_string[] = "Hello World!";
static const char test_string_const[] = "Hello World!";
inline void fennec_test_fproc_strings_cstring() cstring str = test_string;
{ const cstring cstr = test_string_const;
static char test_string[] = "Hello World!";
static const char test_string_const[] = "Hello World!";
cstring str = test_string; fennec_test_run(str, cstr);
const cstring cstr = test_string_const; fennec_test_run(cstr, str);
fennec_test_run(str, cstr); fennec_test_spacer(1);
fennec_test_run(cstr, str);
fennec_test_spacer(1); fennec_test_run(str.length(), static_cast<size_t>(12));
fennec_test_run(str.compare(cstr), 0);
fennec_test_run(str.find('W'), static_cast<size_t>(6));
fennec_test_run(str.find("World"), static_cast<size_t>(6));
fennec_test_run(str.rfind('o'), static_cast<size_t>(7));
fennec_test_run(str.rfind("World"), static_cast<size_t>(6));
fennec_test_run(str.length(), static_cast<size_t>(12)); }
fennec_test_run(str.compare(cstr), 0);
fennec_test_run(str.find('W'), static_cast<size_t>(6));
fennec_test_run(str.find("World"), static_cast<size_t>(6));
fennec_test_run(str.rfind('o'), static_cast<size_t>(7));
fennec_test_run(str.rfind("World"), static_cast<size_t>(6));
}
}
} }

View File

@@ -24,73 +24,68 @@
#include <fennec/fproc/filesystem/file.h> #include <fennec/fproc/filesystem/file.h>
#include <fennec/fproc/filesystem/path.h> #include <fennec/fproc/filesystem/path.h>
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_fproc_io() {
{
inline void fennec_test_fproc_io() { fennec_test_section("utilities");
fennec_test_section("utilities"); fennec_test_spacer(1);
fennec_test_spacer(1); fennec_test_run(path::current(), path(FENNEC_TEST_CWD));
fennec_test_run(path("../" FENNEC_BUILD_NAME "/./test.sh").absolute(), path(FENNEC_TEST_CWD) / "test.sh");
fennec_test_run(path("./test/../test.sh").absolute(), path(FENNEC_TEST_CWD) / "test.sh");
fennec_test_run(path::current().parent(), path("../").absolute());
fennec_test_run(path::current(), path(FENNEC_TEST_CWD)); fennec_test_spacer(2);
fennec_test_run(path("../" FENNEC_BUILD_NAME "/./test.sh").absolute(), path(FENNEC_TEST_CWD) / "test.sh");
fennec_test_run(path("./test/../test.sh").absolute(), path(FENNEC_TEST_CWD) / "test.sh");
fennec_test_run(path::current().parent(), path("../").absolute());
fennec_test_spacer(2);
fennec_test_section("file streams"); fennec_test_section("file streams");
fennec_test_spacer(1); fennec_test_spacer(1);
file stream; file stream;
char data[] = "Hello World!"; char data[] = "Hello World!";
fennec_test_run(stream.open("./test.txt", fmode_write | fmode_trunc), false); fennec_test_run(stream.open("./test.txt", fmode_write | fmode_trunc), false);
fennec_test_run(stream.write(data), sizeof(data)); fennec_test_run(stream.write(data), sizeof(data));
fennec_test_run(stream.close(), false); fennec_test_run(stream.close(), false);
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(stream.open("./test.txt", fmode_read), false); fennec_test_run(stream.open("./test.txt", fmode_read), false);
fennec_test_run(stream.read(data), sizeof(data)); fennec_test_run(stream.read(data), sizeof(data));
fennec_test_run(cstring(data), cstring("Hello World!")); fennec_test_run(cstring(data), cstring("Hello World!"));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(stream.open("./test.txt", fmode_read), false); fennec_test_run(stream.open("./test.txt", fmode_read), false);
fennec_test_run((stream = stream.copy("./copy.txt")).is_open(), true); fennec_test_run((stream = stream.copy("./copy.txt")).is_open(), true);
fennec_test_run(stream.open("./copy.txt", fmode_read), false); fennec_test_run(stream.open("./copy.txt", fmode_read), false);
fennec_test_run(stream.read(data), sizeof(data)); fennec_test_run(stream.read(data), sizeof(data));
fennec_test_run(cstring(data), cstring("Hello World!")); fennec_test_run(cstring(data), cstring("Hello World!"));
fennec_test_run(stream.erase(), false); fennec_test_run(stream.erase(), false);
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(stream.open("./test.txt", fmode_read), false); fennec_test_run(stream.open("./test.txt", fmode_read), false);
fennec_test_run(stream.rename("./rename.txt"), false); fennec_test_run(stream.rename("./rename.txt"), false);
fennec_test_run(stream.open("./rename.txt", fmode_read), false); fennec_test_run(stream.open("./rename.txt", fmode_read), false);
fennec_test_run(stream.read(data), sizeof(data)); fennec_test_run(stream.read(data), sizeof(data));
fennec_test_run(cstring(data), cstring("Hello World!")); fennec_test_run(cstring(data), cstring("Hello World!"));
fennec_test_run(stream.erase(), false); fennec_test_run(stream.erase(), false);
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_section("std streams"); fennec_test_section("std streams");
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(file::cout().write("Hello World!"), sizeof("Hello World!")); fennec_test_run(file::cout().write("Hello World!"), sizeof("Hello World!"));
fennec_test_run(file::cerr().write("Hello World!"), sizeof("Hello World!")); fennec_test_run(file::cerr().write("Hello World!"), sizeof("Hello World!"));
} }
}
} }

View File

@@ -22,23 +22,18 @@
#include "../../test.h" #include "../../test.h"
#include "./strings/test_cstring.h" #include "./strings/test_cstring.h"
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_fproc_strings()
{ {
fennec_test_subheader("cstring");
fennec_test_spacer(2);
fennec_test_fproc_strings_cstring();
fennec_test_spacer(3);
inline void fennec_test_fproc_strings() // TODO
{ }
fennec_test_subheader("cstring");
fennec_test_spacer(2);
fennec_test_fproc_strings_cstring();
fennec_test_spacer(3);
// TODO
}
}
} }

View File

@@ -24,25 +24,20 @@
#include "../../test.h" #include "../../test.h"
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_lang_bits()
{ {
int a = 0x48ef13ad;
int b = 0x23e5ab9c;
inline void fennec_test_lang_bits() fennec_test_run(fennec::bit_cast<float>(0x3ee00000), 0.4375f);
{
int a = 0x48ef13ad;
int b = 0x23e5ab9c;
fennec_test_run(fennec::bit_cast<float>(0x3ee00000), 0.4375f); fennec_test_run(*static_cast<int*>(fennec::bit_and(&a, &b, sizeof(int))), 0x48ef13ad & 0x23e5ab9c);
fennec_test_run(*static_cast<int*>(fennec::bit_or(&a, &b, sizeof(int))), (0x48ef13ad & 0x23e5ab9c) | 0x23e5ab9c);
fennec_test_run(*static_cast<int*>(fennec::bit_and(&a, &b, sizeof(int))), 0x48ef13ad & 0x23e5ab9c); fennec_test_run(*static_cast<int*>(fennec::bit_xor(&a, &b, sizeof(int))), ((0x48ef13ad & 0x23e5ab9c) | 0x23e5ab9c) ^ 0x23e5ab9c);
fennec_test_run(*static_cast<int*>(fennec::bit_or(&a, &b, sizeof(int))), (0x48ef13ad & 0x23e5ab9c) | 0x23e5ab9c); }
fennec_test_run(*static_cast<int*>(fennec::bit_xor(&a, &b, sizeof(int))), ((0x48ef13ad & 0x23e5ab9c) | 0x23e5ab9c) ^ 0x23e5ab9c);
}
}
} }

View File

@@ -19,18 +19,13 @@
#ifndef FENNEC_TEST_LANG_CONDITIONAL_TYPES_H #ifndef FENNEC_TEST_LANG_CONDITIONAL_TYPES_H
#define FENNEC_TEST_LANG_CONDITIONAL_TYPES_H #define FENNEC_TEST_LANG_CONDITIONAL_TYPES_H
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_lang_conditional_types()
{ {
inline void fennec_test_lang_conditional_types()
{
} }
}
} }

View File

@@ -22,35 +22,30 @@
#include <fennec/lang/hashing.h> #include <fennec/lang/hashing.h>
#include "../../test.h" #include "../../test.h"
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_lang_hashing() {
{
inline void fennec_test_lang_hashing() { size_t num = 61;
float_t numf = bit_cast<float>((uint32_t)num);
double_t numd = bit_cast<double>(num);
size_t exp = hash<size_t>()(num);
size_t num = 61; fennec_test_run(hash<int8_t>()(num), exp);
float_t numf = bit_cast<float>((uint32_t)num); fennec_test_run(hash<uint8_t>()(num), exp);
double_t numd = bit_cast<double>(num); fennec_test_run(hash<int16_t>()(num), exp);
size_t exp = hash<size_t>()(num); fennec_test_run(hash<uint16_t>()(num), exp);
fennec_test_run(hash<int32_t>()(num), exp);
fennec_test_run(hash<uint32_t>()(num), exp);
fennec_test_run(hash<int64_t>()(num), exp);
fennec_test_run(hash<uint64_t>()(num), exp);
fennec_test_run(hash<int8_t>()(num), exp); fennec_test_spacer(1);
fennec_test_run(hash<uint8_t>()(num), exp);
fennec_test_run(hash<int16_t>()(num), exp);
fennec_test_run(hash<uint16_t>()(num), exp);
fennec_test_run(hash<int32_t>()(num), exp);
fennec_test_run(hash<uint32_t>()(num), exp);
fennec_test_run(hash<int64_t>()(num), exp);
fennec_test_run(hash<uint64_t>()(num), exp);
fennec_test_spacer(1); fennec_test_run(hash<float_t>()(numf), exp);
fennec_test_run(hash<double_t>()(numd), exp);
fennec_test_run(hash<float_t>()(numf), exp); }
fennec_test_run(hash<double_t>()(numd), exp);
}
}
} }

View File

@@ -21,22 +21,17 @@
#include <fennec/lang/sequences.h> #include <fennec/lang/sequences.h>
namespace fennec namespace fennec::test
{ {
namespace test inline void test_sequences()
{ {
static_assert(fennec::is_same_v<make_index_sequence_t<2>, index_sequence<0, 1>>);
static_assert(fennec::is_same_v<make_index_sequence_t<3>, index_sequence<0, 1, 2>>);
static_assert(fennec::is_same_v<make_index_sequence_t<4>, index_sequence<0, 1, 2, 3>>);
inline void test_sequences() // TODO
{ }
static_assert(fennec::is_same_v<make_index_sequence_t<2>, index_sequence<0, 1>>);
static_assert(fennec::is_same_v<make_index_sequence_t<3>, index_sequence<0, 1, 2>>);
static_assert(fennec::is_same_v<make_index_sequence_t<4>, index_sequence<0, 1, 2, 3>>);
// TODO
}
}
} }

View File

@@ -23,26 +23,21 @@
#include "../../../test.h" #include "../../../test.h"
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_math_quaternion() {
{
inline void fennec_test_math_quaternion() { fennec_test_section("constructors");
fennec_test_section("constructors"); fennec_test_spacer(1);
fennec_test_spacer(1); fennec_test_run(quat(), quat(1, 0, 0, 0));
fennec_test_run(quat(), quat(1, 0, 0, 0)); fennec_test_spacer(2);
fennec_test_spacer(2); // TODO
}
// TODO
}
}
} }

View File

@@ -21,196 +21,191 @@
#include "../../test.h" #include "../../test.h"
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_math_common()
{ {
fennec_test_section("Sign Functions");
inline void fennec_test_math_common() fennec_test_spacer(1);
{
fennec_test_section("Sign Functions");
fennec_test_spacer(1); fennec_test_run(fennec::abs( 1), 1);
fennec_test_run(fennec::abs(-1), 1);
fennec_test_run(fennec::abs( 1.0f), 1.0f);
fennec_test_run(fennec::abs(-1.0f), 1.0f);
fennec_test_run(fennec::abs( 1.0), 1.0);
fennec_test_run(fennec::abs(-1.0), 1.0);
fennec_test_run(fennec::abs( 1), 1); fennec_test_run(fennec::abs(vec2(1.0f, -1.0f)), vec2(1.0f));
fennec_test_run(fennec::abs(-1), 1);
fennec_test_run(fennec::abs( 1.0f), 1.0f);
fennec_test_run(fennec::abs(-1.0f), 1.0f);
fennec_test_run(fennec::abs( 1.0), 1.0);
fennec_test_run(fennec::abs(-1.0), 1.0);
fennec_test_run(fennec::abs(vec2(1.0f, -1.0f)), vec2(1.0f)); fennec_test_spacer(1);
fennec_test_spacer(1); fennec_test_run(fennec::sign(vec2( 1, -2)), vec2( 1, -1));
fennec_test_run(fennec::sign(vec3(-1, 2, -3)), vec3(-1, 1, -1));
fennec_test_run(fennec::sign(vec4( 1, -2, 3, -4)), vec4( 1, -1, 1, -1));
fennec_test_run(fennec::sign(vec2( 1, -2)), vec2( 1, -1)); fennec_test_spacer(2);
fennec_test_run(fennec::sign(vec3(-1, 2, -3)), vec3(-1, 1, -1));
fennec_test_run(fennec::sign(vec4( 1, -2, 3, -4)), vec4( 1, -1, 1, -1));
fennec_test_spacer(2);
fennec_test_section("Rounding Functions");
fennec_test_section("Rounding Functions"); fennec_test_spacer(1);
fennec_test_spacer(1); fennec_test_run(fennec::ceil(2.4f), 3.0f);
fennec_test_run(fennec::ceil(2.5f), 3.0f);
fennec_test_run(fennec::ceil(2.6f), 3.0f);
fennec_test_run(fennec::ceil(2.4f), 3.0f); fennec_test_run(fennec::ceil(-2.4f), -2.0f);
fennec_test_run(fennec::ceil(2.5f), 3.0f); fennec_test_run(fennec::ceil(-2.5f), -2.0f);
fennec_test_run(fennec::ceil(2.6f), 3.0f); fennec_test_run(fennec::ceil(-2.6f), -2.0f);
fennec_test_run(fennec::ceil(-2.4f), -2.0f); fennec_test_spacer(1);
fennec_test_run(fennec::ceil(-2.5f), -2.0f);
fennec_test_run(fennec::ceil(-2.6f), -2.0f);
fennec_test_spacer(1); fennec_test_run(fennec::floor(2.4f), 2.0f);
fennec_test_run(fennec::floor(2.5f), 2.0f);
fennec_test_run(fennec::floor(2.6f), 2.0f);
fennec_test_run(fennec::floor(2.4f), 2.0f); fennec_test_run(fennec::floor(-2.4f), -3.0f);
fennec_test_run(fennec::floor(2.5f), 2.0f); fennec_test_run(fennec::floor(-2.5f), -3.0f);
fennec_test_run(fennec::floor(2.6f), 2.0f); fennec_test_run(fennec::floor(-2.6f), -3.0f);
fennec_test_run(fennec::floor(-2.4f), -3.0f); fennec_test_spacer(1);
fennec_test_run(fennec::floor(-2.5f), -3.0f);
fennec_test_run(fennec::floor(-2.6f), -3.0f);
fennec_test_spacer(1); fennec_test_run(fennec::round(2.4f), 2.0f);
fennec_test_run(fennec::round(2.5f), 3.0f);
fennec_test_run(fennec::round(2.6f), 3.0f);
fennec_test_run(fennec::round(2.4f), 2.0f); fennec_test_spacer(1);
fennec_test_run(fennec::round(2.5f), 3.0f);
fennec_test_run(fennec::round(2.6f), 3.0f);
fennec_test_spacer(1); fennec_test_run(fennec::roundEven(2.4f), 2.0f);
fennec_test_run(fennec::roundEven(2.5f), 2.0f);
fennec_test_run(fennec::roundEven(2.6f), 3.0f);
fennec_test_run(fennec::roundEven(2.4f), 2.0f); fennec_test_spacer(1);
fennec_test_run(fennec::roundEven(2.5f), 2.0f);
fennec_test_run(fennec::roundEven(2.6f), 3.0f);
fennec_test_spacer(1); fennec_test_run(fennec::trunc(2.4f), 2.0f);
fennec_test_run(fennec::trunc(2.5f), 2.0f);
fennec_test_run(fennec::trunc(2.6f), 2.0f);
fennec_test_run(fennec::trunc(2.4f), 2.0f); fennec_test_run(fennec::trunc(-2.4f), -2.0f);
fennec_test_run(fennec::trunc(2.5f), 2.0f); fennec_test_run(fennec::trunc(-2.5f), -2.0f);
fennec_test_run(fennec::trunc(2.6f), 2.0f); fennec_test_run(fennec::trunc(-2.6f), -2.0f);
fennec_test_run(fennec::trunc(-2.4f), -2.0f); fennec_test_spacer(2);
fennec_test_run(fennec::trunc(-2.5f), -2.0f);
fennec_test_run(fennec::trunc(-2.6f), -2.0f);
fennec_test_spacer(2);
fennec_test_section("Floating Point Functions");
fennec_test_section("Floating Point Functions"); fennec_test_spacer(1);
fennec_test_spacer(1); fennec_test_run(fennec::fract(2.4f), 0.4f);
fennec_test_run(fennec::fract(2.5f), 0.5f);
fennec_test_run(fennec::fract(2.6f), 0.6f);
fennec_test_run(fennec::fract(2.4f), 0.4f); fennec_test_spacer(1);
fennec_test_run(fennec::fract(2.5f), 0.5f);
fennec_test_run(fennec::fract(2.6f), 0.6f);
fennec_test_spacer(1); fennec_test_run(fennec::mod(2.4f, 2.0f), 0.4f);
fennec_test_run(fennec::mod(2.5f, 2.0f), 0.5f);
fennec_test_run(fennec::mod(2.6f, 2.0f), 0.6f);
fennec_test_run(fennec::mod(2.4f, 2.0f), 0.4f); fennec_test_spacer(1);
fennec_test_run(fennec::mod(2.5f, 2.0f), 0.5f);
fennec_test_run(fennec::mod(2.6f, 2.0f), 0.6f);
fennec_test_spacer(1); fennec_test_run([]() -> float { float i; return fennec::modf(2.4f, i) + i; }(), 2.4f);
fennec_test_run([]() -> float { float i; return fennec::modf(2.5f, i) + i; }(), 2.5f);
fennec_test_run([]() -> float { float i; return fennec::modf(2.6f, i) + i; }(), 2.6f);
fennec_test_run([]() -> float { float i; return fennec::modf(2.4f, i) + i; }(), 2.4f); fennec_test_spacer(1);
fennec_test_run([]() -> float { float i; return fennec::modf(2.5f, i) + i; }(), 2.5f);
fennec_test_run([]() -> float { float i; return fennec::modf(2.6f, i) + i; }(), 2.6f);
fennec_test_spacer(1); fennec_test_run(fennec::isnan(0.0f), false);
fennec_test_run(fennec::isnan(fennec::numeric_limits<float>::quiet_NaN()), true);
fennec_test_run(fennec::isnan(fennec::numeric_limits<float>::signaling_NaN()), true);
fennec_test_run(fennec::isnan(0.0f), false); fennec_test_spacer(1);
fennec_test_run(fennec::isnan(fennec::numeric_limits<float>::quiet_NaN()), true);
fennec_test_run(fennec::isnan(fennec::numeric_limits<float>::signaling_NaN()), true);
fennec_test_spacer(1); fennec_test_run(fennec::isinf( 0.0f), false);
fennec_test_run(fennec::isinf( fennec::numeric_limits<float>::infinity()), true);
fennec_test_run(fennec::isinf(-fennec::numeric_limits<float>::infinity()), true);
fennec_test_run(fennec::isinf( 0.0f), false); fennec_test_spacer(1);
fennec_test_run(fennec::isinf( fennec::numeric_limits<float>::infinity()), true);
fennec_test_run(fennec::isinf(-fennec::numeric_limits<float>::infinity()), true);
fennec_test_spacer(1); fennec_test_run(fennec::floatBitsToInt( 1.0f), static_cast<int>(0x3f800000u));
fennec_test_run(fennec::floatBitsToInt(-1.0f), static_cast<int>(0xbf800000u));
fennec_test_run(fennec::floatBitsToUint( 1.0f), 0x3f800000u);
fennec_test_run(fennec::floatBitsToUint(-1.0f), 0xbf800000u);
fennec_test_run(fennec::floatBitsToInt( 1.0f), static_cast<int>(0x3f800000u)); fennec_test_spacer(1);
fennec_test_run(fennec::floatBitsToInt(-1.0f), static_cast<int>(0xbf800000u));
fennec_test_run(fennec::floatBitsToUint( 1.0f), 0x3f800000u);
fennec_test_run(fennec::floatBitsToUint(-1.0f), 0xbf800000u);
fennec_test_spacer(1); fennec_test_run(fennec::intBitsToFloat(static_cast<int>(0x3f800000u)), 1.0f);
fennec_test_run(fennec::intBitsToFloat(static_cast<int>(0xbf800000u)), -1.0f);
fennec_test_run(fennec::uintBitsToFloat(0x3f800000u), 1.0f);
fennec_test_run(fennec::uintBitsToFloat(0xbf800000u), -1.0f);
fennec_test_run(fennec::intBitsToFloat(static_cast<int>(0x3f800000u)), 1.0f); fennec_test_spacer(1);
fennec_test_run(fennec::intBitsToFloat(static_cast<int>(0xbf800000u)), -1.0f);
fennec_test_run(fennec::uintBitsToFloat(0x3f800000u), 1.0f);
fennec_test_run(fennec::uintBitsToFloat(0xbf800000u), -1.0f);
fennec_test_spacer(1); fennec_test_run(fennec::fma( 1, 2, 3), 5);
fennec_test_run(fennec::fma(-1, 2, -3), -5);
fennec_test_run(fennec::fma( 1, -2, 3), 1);
fennec_test_run(fennec::fma( 1, 2, 3), 5); fennec_test_spacer(1);
fennec_test_run(fennec::fma(-1, 2, -3), -5);
fennec_test_run(fennec::fma( 1, -2, 3), 1);
fennec_test_spacer(1); fennec_test_run([]() -> float { int i; float f = fennec::frexp(2.4f, i); return fennec::ldexp(f, i); }(), 2.4f);
fennec_test_run([]() -> float { int i; float f = fennec::frexp(2.5f, i); return fennec::ldexp(f, i); }(), 2.5f);
fennec_test_run([]() -> float { int i; float f = fennec::frexp(2.6f, i); return fennec::ldexp(f, i); }(), 2.6f);
fennec_test_run([]() -> float { int i; float f = fennec::frexp(2.4f, i); return fennec::ldexp(f, i); }(), 2.4f); fennec_test_spacer(2);
fennec_test_run([]() -> float { int i; float f = fennec::frexp(2.5f, i); return fennec::ldexp(f, i); }(), 2.5f);
fennec_test_run([]() -> float { int i; float f = fennec::frexp(2.6f, i); return fennec::ldexp(f, i); }(), 2.6f);
fennec_test_spacer(2);
fennec_test_section("Comparison Functions");
fennec_test_section("Comparison Functions"); fennec_test_spacer(1);
fennec_test_spacer(1); fennec_test_run(min(2.0f, 1.0f), 1.0f);
fennec_test_run(min(-fennec::numeric_limits<float>::infinity(), 0.0f), -fennec::numeric_limits<float>::infinity());
fennec_test_run(min(2.0f, 1.0f), 1.0f); fennec_test_spacer(1);
fennec_test_run(min(-fennec::numeric_limits<float>::infinity(), 0.0f), -fennec::numeric_limits<float>::infinity());
fennec_test_spacer(1); fennec_test_run(max(2.0f, 1.0f), 2.0f);
fennec_test_run(max(-fennec::numeric_limits<float>::infinity(), 0.0f), 0.0f);
fennec_test_run(max(2.0f, 1.0f), 2.0f); fennec_test_spacer(1);
fennec_test_run(max(-fennec::numeric_limits<float>::infinity(), 0.0f), 0.0f);
fennec_test_spacer(1); fennec_test_run(clamp(-0.5f, 0.0f, 1.0f), 0.0f);
fennec_test_run(clamp( 0.5f, 0.0f, 1.0f), 0.5f);
fennec_test_run(clamp( 1.5f, 0.0f, 1.0f), 1.0f);
fennec_test_run(clamp(-0.5f, 0.0f, 1.0f), 0.0f); fennec_test_spacer(2);
fennec_test_run(clamp( 0.5f, 0.0f, 1.0f), 0.5f);
fennec_test_run(clamp( 1.5f, 0.0f, 1.0f), 1.0f);
fennec_test_spacer(2);
fennec_test_section("Curves");
fennec_test_section("Curves"); fennec_test_spacer(1);
fennec_test_spacer(1); fennec_test_run(step(2.5f, 2.4f), 0.0f);
fennec_test_run(step(2.5f, 2.5f), 1.0f);
fennec_test_run(step(2.5f, 2.6f), 1.0f);
fennec_test_run(step(2.5f, 2.4f), 0.0f); fennec_test_spacer(1);
fennec_test_run(step(2.5f, 2.5f), 1.0f);
fennec_test_run(step(2.5f, 2.6f), 1.0f);
fennec_test_spacer(1); fennec_test_run(smoothstep(0.0f, 1.0f, -0.5f), 0.0f);
fennec_test_run(smoothstep(0.0f, 1.0f, 0.5f), 0.5f);
fennec_test_run(smoothstep(0.0f, 1.0f, 1.5f), 1.0f);
fennec_test_run(smoothstep(0.0f, 1.0f, -0.5f), 0.0f); fennec_test_spacer(1);
fennec_test_run(smoothstep(0.0f, 1.0f, 0.5f), 0.5f);
fennec_test_run(smoothstep(0.0f, 1.0f, 1.5f), 1.0f);
fennec_test_spacer(1); fennec_test_run(mix(0.0f, 1.0f, -0.5f), -0.5f);
fennec_test_run(mix(0.0f, 1.0f, 0.5f), 0.5f);
fennec_test_run(mix(0.0f, 1.0f, 1.5f), 1.5f);
fennec_test_run(mix(0.0f, 1.0f, -0.5f), -0.5f); fennec_test_spacer(1);
fennec_test_run(mix(0.0f, 1.0f, 0.5f), 0.5f);
fennec_test_run(mix(0.0f, 1.0f, 1.5f), 1.5f);
fennec_test_spacer(1); fennec_test_run(mix(0.0f, 1.0f, false), 0.0f);
fennec_test_run(mix(0.0f, 1.0f, true), 1.0f);
fennec_test_run(mix(0.0f, 1.0f, false), 0.0f); }
fennec_test_run(mix(0.0f, 1.0f, true), 1.0f);
}
}
} }

View File

@@ -24,60 +24,55 @@
#include <fennec/math/exponential.h> #include <fennec/math/exponential.h>
#include <fennec/math/ext/constants.h> #include <fennec/math/ext/constants.h>
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_math_exponential()
{ {
fennec_test_run(fennec::pow(1.0f, 2.0f), 1.0f);
fennec_test_run(fennec::pow(2.0f, 0.0f), 1.0f);
fennec_test_run(fennec::pow(2.0f, 1.0f), 2.0f);
fennec_test_run(fennec::pow(2.0f, 2.0f), 4.0f);
inline void fennec_test_math_exponential() fennec_test_spacer(1);
{
fennec_test_run(fennec::pow(1.0f, 2.0f), 1.0f);
fennec_test_run(fennec::pow(2.0f, 0.0f), 1.0f);
fennec_test_run(fennec::pow(2.0f, 1.0f), 2.0f);
fennec_test_run(fennec::pow(2.0f, 2.0f), 4.0f);
fennec_test_spacer(1); fennec_test_run(fennec::exp(-1.0f), fennec::one_over_e<float>());
fennec_test_run(fennec::exp( 0.0f), 1.0f);
fennec_test_run(fennec::exp( 1.0f), fennec::e<float>());
fennec_test_run(fennec::exp( 2.0f), fennec::e_sq<float>());
fennec_test_run(fennec::exp(-1.0f), fennec::one_over_e<float>()); fennec_test_spacer(1);
fennec_test_run(fennec::exp( 0.0f), 1.0f);
fennec_test_run(fennec::exp( 1.0f), fennec::e<float>());
fennec_test_run(fennec::exp( 2.0f), fennec::e_sq<float>());
fennec_test_spacer(1); fennec_test_run(fennec::exp2(-1.0f), 0.5f);
fennec_test_run(fennec::exp2( 0.0f), 1.0f);
fennec_test_run(fennec::exp2( 1.0f), 2.0f);
fennec_test_run(fennec::exp2( 2.0f), 4.0f);
fennec_test_run(fennec::exp2(-1.0f), 0.5f); fennec_test_spacer(1);
fennec_test_run(fennec::exp2( 0.0f), 1.0f);
fennec_test_run(fennec::exp2( 1.0f), 2.0f);
fennec_test_run(fennec::exp2( 2.0f), 4.0f);
fennec_test_spacer(1); fennec_test_run(fennec::log(fennec::one_over_e<float>()), -1.0f);
fennec_test_run(fennec::log(1.0f), 0.0f);
fennec_test_run(fennec::log(fennec::e<float>()), 1.0f);
fennec_test_run(fennec::log(fennec::e_sq<float>()), 2.0f);
fennec_test_run(fennec::log(fennec::one_over_e<float>()), -1.0f); fennec_test_spacer(1);
fennec_test_run(fennec::log(1.0f), 0.0f);
fennec_test_run(fennec::log(fennec::e<float>()), 1.0f);
fennec_test_run(fennec::log(fennec::e_sq<float>()), 2.0f);
fennec_test_spacer(1); fennec_test_run(fennec::log2(1.0f), 0.0f);
fennec_test_run(fennec::log2(2.0f), 1.0f);
fennec_test_run(fennec::log2(4.0f), 2.0f);
fennec_test_run(fennec::log2(1.0f), 0.0f); fennec_test_spacer(1);
fennec_test_run(fennec::log2(2.0f), 1.0f);
fennec_test_run(fennec::log2(4.0f), 2.0f);
fennec_test_spacer(1); fennec_test_run(fennec::sqrt(1.0f), 1.0f);
fennec_test_run(fennec::sqrt(4.0f), 2.0f);
fennec_test_run(fennec::sqrt(9.0f), 3.0f);
fennec_test_run(fennec::sqrt(1.0f), 1.0f); fennec_test_spacer(1);
fennec_test_run(fennec::sqrt(4.0f), 2.0f);
fennec_test_run(fennec::sqrt(9.0f), 3.0f);
fennec_test_spacer(1); fennec_test_run(fennec::inversesqrt(1.0f), 1.0f / 1.0f);
fennec_test_run(fennec::inversesqrt(4.0f), 1.0f / 2.0f);
fennec_test_run(fennec::inversesqrt(1.0f), 1.0f / 1.0f); fennec_test_run(fennec::inversesqrt(9.0f), 1.0f / 3.0f);
fennec_test_run(fennec::inversesqrt(4.0f), 1.0f / 2.0f); }
fennec_test_run(fennec::inversesqrt(9.0f), 1.0f / 3.0f);
}
}
} }

View File

@@ -23,23 +23,18 @@
#ifndef FENNEC_TEST_MATH_EXT_H #ifndef FENNEC_TEST_MATH_EXT_H
#define FENNEC_TEST_MATH_EXT_H #define FENNEC_TEST_MATH_EXT_H
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_math_ext() {
{
inline void fennec_test_math_ext() { fennec_test_subheader("quaternion tests");
fennec_test_spacer(2);
fennec_test_math_quaternion();
fennec_test_spacer(3);
fennec_test_subheader("quaternion tests"); // TODO
fennec_test_spacer(2); }
fennec_test_math_quaternion();
fennec_test_spacer(3);
// TODO
}
}
} }

View File

@@ -25,61 +25,56 @@
#include "../../test.h" #include "../../test.h"
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_math_geometric()
{ {
inline void fennec_test_math_geometric() fennec_test_run(fennec::dot(vec2(1, 2), vec2(1, 2)), 5.0f);
{ fennec_test_run(fennec::dot(vec3(1, 2, 3), vec3(1, 2, 3)), 14.0f);
fennec_test_run(fennec::dot(vec4(1, 2, 3, 4), vec4(1, 2, 3, 4)), 30.0f);
fennec_test_run(fennec::dot(vec2(1, 2), vec2(1, 2)), 5.0f); fennec_test_spacer(1);
fennec_test_run(fennec::dot(vec3(1, 2, 3), vec3(1, 2, 3)), 14.0f);
fennec_test_run(fennec::dot(vec4(1, 2, 3, 4), vec4(1, 2, 3, 4)), 30.0f);
fennec_test_spacer(1); fennec_test_run(fennec::length2(vec2(1, 2) ), 5.0f);
fennec_test_run(fennec::length2(vec3(1, 2, 3) ), 14.0f);
fennec_test_run(fennec::length2(vec4(1, 2, 3, 4)), 30.0f);
fennec_test_run(fennec::length2(vec2(1, 2) ), 5.0f); fennec_test_spacer(1);
fennec_test_run(fennec::length2(vec3(1, 2, 3) ), 14.0f);
fennec_test_run(fennec::length2(vec4(1, 2, 3, 4)), 30.0f);
fennec_test_spacer(1); fennec_test_run(fennec::length(vec2(1, 2) ), sqrt(5.0f));
fennec_test_run(fennec::length(vec3(1, 2, 3) ), sqrt(14.0f));
fennec_test_run(fennec::length(vec4(1, 2, 3, 4)), sqrt(30.0f));
fennec_test_run(fennec::length(vec2(1, 2) ), sqrt(5.0f)); fennec_test_spacer(1);
fennec_test_run(fennec::length(vec3(1, 2, 3) ), sqrt(14.0f));
fennec_test_run(fennec::length(vec4(1, 2, 3, 4)), sqrt(30.0f));
fennec_test_spacer(1); fennec_test_run(fennec::distance(vec2(1, 2), vec2(2, 1)), sqrt(2.0f));
fennec_test_run(fennec::distance(vec3(1, 2, 3), vec3(3, 2, 1)), sqrt(8.0f));
fennec_test_run(fennec::distance(vec4(1, 2, 3, 4), vec4(4, 3, 2, 1)), sqrt(20.0f));
fennec_test_run(fennec::distance(vec2(1, 2), vec2(2, 1)), sqrt(2.0f)); fennec_test_spacer(1);
fennec_test_run(fennec::distance(vec3(1, 2, 3), vec3(3, 2, 1)), sqrt(8.0f));
fennec_test_run(fennec::distance(vec4(1, 2, 3, 4), vec4(4, 3, 2, 1)), sqrt(20.0f));
fennec_test_spacer(1); fennec_test_run(fennec::cross(vec3(1, 0, 0), vec3(0, 1, 0)), vec3(0, 0, 1));
fennec_test_run(fennec::cross(vec3(0, 1, 0), vec3(0, 0, 1)), vec3(1, 0, 0));
fennec_test_run(fennec::cross(vec3(0, 0, 1), vec3(1, 0, 0)), vec3(0, 1, 0));
fennec_test_run(fennec::cross(vec3(1, 0, 0), vec3(0, 1, 0)), vec3(0, 0, 1)); fennec_test_spacer(1);
fennec_test_run(fennec::cross(vec3(0, 1, 0), vec3(0, 0, 1)), vec3(1, 0, 0));
fennec_test_run(fennec::cross(vec3(0, 0, 1), vec3(1, 0, 0)), vec3(0, 1, 0));
fennec_test_spacer(1); fennec_test_run(fennec::normalize(vec2(1, 1)), vec2(sqrt(2.0f) / 2.0f, sqrt(2.0f) / 2.0f));
fennec_test_run(fennec::normalize(vec3(1, 1, 1)), vec3(sqrt(3.0f) / 3.0f, sqrt(3.0f) / 3.0f, sqrt(3.0f) / 3.0f));
fennec_test_run(fennec::normalize(vec4(1, 1, 1, 1)), vec4(0.5f, 0.5f, 0.5f, 0.5f));
fennec_test_run(fennec::normalize(vec2(1, 1)), vec2(sqrt(2.0f) / 2.0f, sqrt(2.0f) / 2.0f)); fennec_test_spacer(1);
fennec_test_run(fennec::normalize(vec3(1, 1, 1)), vec3(sqrt(3.0f) / 3.0f, sqrt(3.0f) / 3.0f, sqrt(3.0f) / 3.0f));
fennec_test_run(fennec::normalize(vec4(1, 1, 1, 1)), vec4(0.5f, 0.5f, 0.5f, 0.5f));
fennec_test_spacer(1); fennec_test_run(fennec::faceforward(vec3(1, 0, 0), vec3(-1, 0, 0), vec3(1, 0, 0)), vec3(-1, 0, 0));
fennec_test_run(fennec::faceforward(vec3(1, 0, 0), vec3(-1, 0, 0), vec3(-1, 0, 0)), vec3( 1, 0, 0));
fennec_test_run(fennec::faceforward(vec3(1, 0, 0), vec3(-1, 0, 0), vec3(1, 0, 0)), vec3(-1, 0, 0)); fennec_test_spacer(1);
fennec_test_run(fennec::faceforward(vec3(1, 0, 0), vec3(-1, 0, 0), vec3(-1, 0, 0)), vec3( 1, 0, 0));
fennec_test_spacer(1); fennec_test_run(fennec::reflect(vec2(1, -1), vec2(0, 1)), vec2(1, 1));
fennec_test_run(fennec::refract(vec2(1, -1), vec2(0, 1), 1/1.33f), vec2(0.7518797, -1));
fennec_test_run(fennec::reflect(vec2(1, -1), vec2(0, 1)), vec2(1, 1)); }
fennec_test_run(fennec::refract(vec2(1, -1), vec2(0, 1), 1/1.33f), vec2(0.7518797, -1));
}
}
} }

View File

@@ -26,303 +26,298 @@
#include <iostream> #include <iostream>
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_math_matrix()
{ {
fennec_test_section("component_count");
inline void fennec_test_math_matrix() fennec_test_spacer(1);
{
fennec_test_section("component_count");
fennec_test_spacer(1); fennec_test_run((component_count_v<mat2x2> == 4), true);
fennec_test_run((component_count_v<mat2x3> == 6), true);
fennec_test_run((component_count_v<mat3x2> == 6), true);
fennec_test_run((component_count_v<mat3x3> == 9), true);
fennec_test_run((component_count_v<mat3x4> == 12), true);
fennec_test_run((component_count_v<mat4x3> == 12), true);
fennec_test_run((component_count_v<mat4x4> == 16), true);
fennec_test_run((component_count_v<mat2x2> == 4), true); fennec_test_spacer(1);
fennec_test_run((component_count_v<mat2x3> == 6), true);
fennec_test_run((component_count_v<mat3x2> == 6), true);
fennec_test_run((component_count_v<mat3x3> == 9), true);
fennec_test_run((component_count_v<mat3x4> == 12), true);
fennec_test_run((component_count_v<mat4x3> == 12), true);
fennec_test_run((component_count_v<mat4x4> == 16), true);
fennec_test_spacer(1); fennec_test_run((component_count_v<mat2x2&> == 4), true);
fennec_test_run((component_count_v<mat2x3&> == 6), true);
fennec_test_run((component_count_v<mat3x2&> == 6), true);
fennec_test_run((component_count_v<mat3x3&> == 9), true);
fennec_test_run((component_count_v<mat3x4&> == 12), true);
fennec_test_run((component_count_v<mat4x3&> == 12), true);
fennec_test_run((component_count_v<mat4x4&> == 16), true);
fennec_test_run((component_count_v<mat2x2&> == 4), true); fennec_test_spacer(1);
fennec_test_run((component_count_v<mat2x3&> == 6), true);
fennec_test_run((component_count_v<mat3x2&> == 6), true);
fennec_test_run((component_count_v<mat3x3&> == 9), true);
fennec_test_run((component_count_v<mat3x4&> == 12), true);
fennec_test_run((component_count_v<mat4x3&> == 12), true);
fennec_test_run((component_count_v<mat4x4&> == 16), true);
fennec_test_spacer(1); fennec_test_run((component_count_v<mat2x2&&> == 4), true);
fennec_test_run((component_count_v<mat2x3&&> == 6), true);
fennec_test_run((component_count_v<mat3x2&&> == 6), true);
fennec_test_run((component_count_v<mat3x3&&> == 9), true);
fennec_test_run((component_count_v<mat3x4&&> == 12), true);
fennec_test_run((component_count_v<mat4x3&&> == 12), true);
fennec_test_run((component_count_v<mat4x4&&> == 16), true);
fennec_test_run((component_count_v<mat2x2&&> == 4), true); fennec_test_spacer(1);
fennec_test_run((component_count_v<mat2x3&&> == 6), true);
fennec_test_run((component_count_v<mat3x2&&> == 6), true);
fennec_test_run((component_count_v<mat3x3&&> == 9), true);
fennec_test_run((component_count_v<mat3x4&&> == 12), true);
fennec_test_run((component_count_v<mat4x3&&> == 12), true);
fennec_test_run((component_count_v<mat4x4&&> == 16), true);
fennec_test_spacer(1); fennec_test_run((component_count_v<const mat2x2&> == 4), true);
fennec_test_run((component_count_v<const mat2x3&> == 6), true);
fennec_test_run((component_count_v<const mat3x2&> == 6), true);
fennec_test_run((component_count_v<const mat3x3&> == 9), true);
fennec_test_run((component_count_v<const mat3x4&> == 12), true);
fennec_test_run((component_count_v<const mat4x3&> == 12), true);
fennec_test_run((component_count_v<const mat4x4&> == 16), true);
fennec_test_run((component_count_v<const mat2x2&> == 4), true); fennec_test_spacer(2);
fennec_test_run((component_count_v<const mat2x3&> == 6), true);
fennec_test_run((component_count_v<const mat3x2&> == 6), true);
fennec_test_run((component_count_v<const mat3x3&> == 9), true);
fennec_test_run((component_count_v<const mat3x4&> == 12), true);
fennec_test_run((component_count_v<const mat4x3&> == 12), true);
fennec_test_run((component_count_v<const mat4x4&> == 16), true);
fennec_test_spacer(2); fennec_test_run((component_count_v<dmat2x2> == 4), true);
fennec_test_run((component_count_v<dmat2x3> == 6), true);
fennec_test_run((component_count_v<dmat3x2> == 6), true);
fennec_test_run((component_count_v<dmat3x3> == 9), true);
fennec_test_run((component_count_v<dmat3x4> == 12), true);
fennec_test_run((component_count_v<dmat4x3> == 12), true);
fennec_test_run((component_count_v<dmat4x4> == 16), true);
fennec_test_run((component_count_v<dmat2x2> == 4), true); fennec_test_spacer(1);
fennec_test_run((component_count_v<dmat2x3> == 6), true);
fennec_test_run((component_count_v<dmat3x2> == 6), true);
fennec_test_run((component_count_v<dmat3x3> == 9), true);
fennec_test_run((component_count_v<dmat3x4> == 12), true);
fennec_test_run((component_count_v<dmat4x3> == 12), true);
fennec_test_run((component_count_v<dmat4x4> == 16), true);
fennec_test_spacer(1); fennec_test_run((component_count_v<dmat2x2&> == 4), true);
fennec_test_run((component_count_v<dmat2x3&> == 6), true);
fennec_test_run((component_count_v<dmat3x2&> == 6), true);
fennec_test_run((component_count_v<dmat3x3&> == 9), true);
fennec_test_run((component_count_v<dmat3x4&> == 12), true);
fennec_test_run((component_count_v<dmat4x3&> == 12), true);
fennec_test_run((component_count_v<dmat4x4&> == 16), true);
fennec_test_run((component_count_v<dmat2x2&> == 4), true); fennec_test_spacer(1);
fennec_test_run((component_count_v<dmat2x3&> == 6), true);
fennec_test_run((component_count_v<dmat3x2&> == 6), true);
fennec_test_run((component_count_v<dmat3x3&> == 9), true);
fennec_test_run((component_count_v<dmat3x4&> == 12), true);
fennec_test_run((component_count_v<dmat4x3&> == 12), true);
fennec_test_run((component_count_v<dmat4x4&> == 16), true);
fennec_test_spacer(1); fennec_test_run((component_count_v<dmat2x2&&> == 4), true);
fennec_test_run((component_count_v<dmat2x3&&> == 6), true);
fennec_test_run((component_count_v<dmat3x2&&> == 6), true);
fennec_test_run((component_count_v<dmat3x3&&> == 9), true);
fennec_test_run((component_count_v<dmat3x4&&> == 12), true);
fennec_test_run((component_count_v<dmat4x3&&> == 12), true);
fennec_test_run((component_count_v<dmat4x4&&> == 16), true);
fennec_test_run((component_count_v<dmat2x2&&> == 4), true); fennec_test_spacer(1);
fennec_test_run((component_count_v<dmat2x3&&> == 6), true);
fennec_test_run((component_count_v<dmat3x2&&> == 6), true);
fennec_test_run((component_count_v<dmat3x3&&> == 9), true);
fennec_test_run((component_count_v<dmat3x4&&> == 12), true);
fennec_test_run((component_count_v<dmat4x3&&> == 12), true);
fennec_test_run((component_count_v<dmat4x4&&> == 16), true);
fennec_test_spacer(1); fennec_test_run((component_count_v<const dmat2x2&> == 4), true);
fennec_test_run((component_count_v<const dmat2x3&> == 6), true);
fennec_test_run((component_count_v<const dmat3x2&> == 6), true);
fennec_test_run((component_count_v<const dmat3x3&> == 9), true);
fennec_test_run((component_count_v<const dmat3x4&> == 12), true);
fennec_test_run((component_count_v<const dmat4x3&> == 12), true);
fennec_test_run((component_count_v<const dmat4x4&> == 16), true);
fennec_test_run((component_count_v<const dmat2x2&> == 4), true); fennec_test_spacer(2);
fennec_test_run((component_count_v<const dmat2x3&> == 6), true);
fennec_test_run((component_count_v<const dmat3x2&> == 6), true);
fennec_test_run((component_count_v<const dmat3x3&> == 9), true);
fennec_test_run((component_count_v<const dmat3x4&> == 12), true);
fennec_test_run((component_count_v<const dmat4x3&> == 12), true);
fennec_test_run((component_count_v<const dmat4x4&> == 16), true);
fennec_test_spacer(2);
fennec_test_section("matrix equality operators");
fennec_test_section("matrix equality operators"); fennec_test_spacer(1);
fennec_test_spacer(1); fennec_test_run(mat2() == mat2(), true);
fennec_test_run(mat3() == mat3(), true);
fennec_test_run(mat4() == mat4(), true);
fennec_test_run(mat2() == mat2(), true); fennec_test_spacer(1);
fennec_test_run(mat3() == mat3(), true);
fennec_test_run(mat4() == mat4(), true);
fennec_test_spacer(1); fennec_test_run(mat2() != mat2(), false);
fennec_test_run(mat3() != mat3(), false);
fennec_test_run(mat4() != mat4(), false);
fennec_test_run(mat2() != mat2(), false); fennec_test_spacer(2);
fennec_test_run(mat3() != mat3(), false);
fennec_test_run(mat4() != mat4(), false);
fennec_test_spacer(2);
fennec_test_section("matrix constructors");
fennec_test_section("matrix constructors"); fennec_test_spacer(1);
fennec_test_spacer(1); fennec_test_run(mat2(), mat2(0));
fennec_test_run(mat3(), mat3(0));
fennec_test_run(mat4(), mat4(0));
fennec_test_run(mat2(), mat2(0)); fennec_test_spacer(1);
fennec_test_run(mat3(), mat3(0));
fennec_test_run(mat4(), mat4(0));
fennec_test_spacer(1); fennec_test_run(mat2(1), mat2(1, 0, 0, 1));
fennec_test_run(mat3(1), mat3(1, 0, 0, 0, 1, 0, 0, 0, 1));
fennec_test_run(mat4(1), mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1));
fennec_test_run(mat2(1), mat2(1, 0, 0, 1)); fennec_test_spacer(2);
fennec_test_run(mat3(1), mat3(1, 0, 0, 0, 1, 0, 0, 0, 1));
fennec_test_run(mat4(1), mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1));
fennec_test_spacer(2);
fennec_test_section("matrix-scalar operators");
fennec_test_section("matrix-scalar operators"); fennec_test_spacer(1);
fennec_test_spacer(1); fennec_test_run(mat2x2(1, 2, 3, 4) * 2, mat2x2(2, 4, 6, 8));
fennec_test_run(mat2x3(1, 2, 3, 4, 5, 6) * 2, mat2x3(2, 4, 6, 8, 10, 12));
fennec_test_run(mat3x2(1, 2, 3, 4, 5, 6) * 2, mat3x2(2, 4, 6, 8, 10, 12));
fennec_test_run(mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9) * 2, mat3x3(2, 4, 6, 8, 10, 12, 14, 16, 18));
fennec_test_run(mat2x2(1, 2, 3, 4) * 2, mat2x2(2, 4, 6, 8)); fennec_test_spacer(2);
fennec_test_run(mat2x3(1, 2, 3, 4, 5, 6) * 2, mat2x3(2, 4, 6, 8, 10, 12));
fennec_test_run(mat3x2(1, 2, 3, 4, 5, 6) * 2, mat3x2(2, 4, 6, 8, 10, 12));
fennec_test_run(mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9) * 2, mat3x3(2, 4, 6, 8, 10, 12, 14, 16, 18));
fennec_test_spacer(2);
fennec_test_section("matrix-vector operators");
fennec_test_section("matrix-vector operators"); fennec_test_spacer(1);
fennec_test_spacer(1); fennec_test_run(vec2(1, 2) * mat2x2(1, 2, 3, 4), vec2(5, 11));
fennec_test_run(vec2(1, 2) * mat3x2(1, 2, 3, 4, 5, 6), vec3(5, 11, 17));
fennec_test_run(vec2(1, 2) * mat4x2(1, 2, 3, 4, 5, 6, 7, 8), vec4(5, 11, 17, 23));
fennec_test_run(vec2(1, 2) * mat2x2(1, 2, 3, 4), vec2(5, 11)); fennec_test_spacer(1);
fennec_test_run(vec2(1, 2) * mat3x2(1, 2, 3, 4, 5, 6), vec3(5, 11, 17));
fennec_test_run(vec2(1, 2) * mat4x2(1, 2, 3, 4, 5, 6, 7, 8), vec4(5, 11, 17, 23));
fennec_test_spacer(1); fennec_test_run(vec3(1, 2, 3) * mat2x3(1, 2, 3, 4, 5, 6), vec2(14, 32));
fennec_test_run(vec3(1, 2, 3) * mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9), vec3(14, 32, 50));
fennec_test_run(vec3(1, 2, 3) * mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), vec4(14, 32, 50, 68));
fennec_test_run(vec3(1, 2, 3) * mat2x3(1, 2, 3, 4, 5, 6), vec2(14, 32)); fennec_test_spacer(2);
fennec_test_run(vec3(1, 2, 3) * mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9), vec3(14, 32, 50));
fennec_test_run(vec3(1, 2, 3) * mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), vec4(14, 32, 50, 68));
fennec_test_spacer(2);
fennec_test_section("matrix-matrix operators");
fennec_test_section("matrix-matrix operators"); fennec_test_spacer(1);
fennec_test_spacer(1); fennec_test_run(mat2x2(1, 2, 3, 4) * mat2x2(1, 2, 3, 4), mat2x2(7, 10, 15, 22));
fennec_test_run(mat2x2(1, 2, 3, 4) * mat3x2(1, 2, 3, 4, 5, 6), mat3x2(7, 10, 15, 22, 23, 34));
fennec_test_run(mat2x2(1, 2, 3, 4) * mat4x2(1, 2, 3, 4, 5, 6, 7, 8), mat4x2(7, 10, 15, 22, 23, 34, 31, 46));
fennec_test_run(mat2x2(1, 2, 3, 4) * mat2x2(1, 2, 3, 4), mat2x2(7, 10, 15, 22)); fennec_test_spacer(1);
fennec_test_run(mat2x2(1, 2, 3, 4) * mat3x2(1, 2, 3, 4, 5, 6), mat3x2(7, 10, 15, 22, 23, 34));
fennec_test_run(mat2x2(1, 2, 3, 4) * mat4x2(1, 2, 3, 4, 5, 6, 7, 8), mat4x2(7, 10, 15, 22, 23, 34, 31, 46));
fennec_test_spacer(1); fennec_test_run(mat2x3(1, 2, 3, 4, 5, 6) * mat2x2(1, 2, 3, 4), mat2x3(9, 12, 15, 19, 26, 33));
fennec_test_run(mat2x3(1, 2, 3, 4, 5, 6) * mat3x2(1, 2, 3, 4, 5, 6), mat3x3(9, 12, 15, 19, 26, 33, 29, 40, 51));
fennec_test_run(mat2x3(1, 2, 3, 4, 5, 6) * mat4x2(1, 2, 3, 4, 5, 6, 7, 8), mat4x3(9, 12, 15, 19, 26, 33, 29, 40, 51, 39, 54, 69));
fennec_test_run(mat2x3(1, 2, 3, 4, 5, 6) * mat2x2(1, 2, 3, 4), mat2x3(9, 12, 15, 19, 26, 33)); fennec_test_spacer(1);
fennec_test_run(mat2x3(1, 2, 3, 4, 5, 6) * mat3x2(1, 2, 3, 4, 5, 6), mat3x3(9, 12, 15, 19, 26, 33, 29, 40, 51));
fennec_test_run(mat2x3(1, 2, 3, 4, 5, 6) * mat4x2(1, 2, 3, 4, 5, 6, 7, 8), mat4x3(9, 12, 15, 19, 26, 33, 29, 40, 51, 39, 54, 69));
fennec_test_spacer(1); fennec_test_run(mat3x2(1, 2, 3, 4, 5, 6) * mat2x3(1, 2, 3, 4, 5, 6), mat2x2(22, 28, 49, 64));
fennec_test_run(mat3x2(1, 2, 3, 4, 5, 6) * mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9), mat3x2(22, 28, 49, 64, 76, 100));
fennec_test_run(mat3x2(1, 2, 3, 4, 5, 6) * mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), mat4x2(22, 28, 49, 64, 76, 100, 103, 136));
fennec_test_run(mat3x2(1, 2, 3, 4, 5, 6) * mat2x3(1, 2, 3, 4, 5, 6), mat2x2(22, 28, 49, 64)); fennec_test_spacer(1);
fennec_test_run(mat3x2(1, 2, 3, 4, 5, 6) * mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9), mat3x2(22, 28, 49, 64, 76, 100));
fennec_test_run(mat3x2(1, 2, 3, 4, 5, 6) * mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), mat4x2(22, 28, 49, 64, 76, 100, 103, 136));
fennec_test_spacer(1); fennec_test_run(mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9) * mat2x3(1, 2, 3, 4, 5, 6), mat2x3(30, 36, 42, 66, 81, 96));
fennec_test_run(mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9) * mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9), mat3x3(30, 36, 42, 66, 81, 96, 102, 126, 150));
fennec_test_run(mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9) * mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), mat4x3(30, 36, 42, 66, 81, 96, 102, 126, 150, 138, 171, 204));
fennec_test_run(mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9) * mat2x3(1, 2, 3, 4, 5, 6), mat2x3(30, 36, 42, 66, 81, 96)); fennec_test_spacer(1);
fennec_test_run(mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9) * mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9), mat3x3(30, 36, 42, 66, 81, 96, 102, 126, 150));
fennec_test_run(mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9) * mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), mat4x3(30, 36, 42, 66, 81, 96, 102, 126, 150, 138, 171, 204));
fennec_test_spacer(1); fennec_test_run(mat3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) * mat2x3(1, 2, 3, 4, 5, 6), mat2x4(38, 44, 50, 56, 83, 98, 113, 128));
fennec_test_run(mat3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) * mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9), mat3x4(38, 44, 50, 56, 83, 98, 113, 128, 128, 152, 176, 200));
fennec_test_run(mat3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) * mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), mat4x4(38, 44, 50, 56, 83, 98, 113, 128, 128, 152, 176, 200, 173, 206, 239, 272));
fennec_test_run(mat3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) * mat2x3(1, 2, 3, 4, 5, 6), mat2x4(38, 44, 50, 56, 83, 98, 113, 128)); fennec_test_spacer(1);
fennec_test_run(mat3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) * mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9), mat3x4(38, 44, 50, 56, 83, 98, 113, 128, 128, 152, 176, 200));
fennec_test_run(mat3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) * mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), mat4x4(38, 44, 50, 56, 83, 98, 113, 128, 128, 152, 176, 200, 173, 206, 239, 272));
fennec_test_spacer(1); fennec_test_run(mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) * mat2x4(1, 2, 3, 4, 5, 6, 7, 8), mat2x3(70, 80, 90, 158, 184, 210));
fennec_test_run(mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) * mat3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), mat3x3(70, 80, 90, 158, 184, 210, 246, 288, 330));
fennec_test_run(mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) * mat4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), mat4x3(70, 80, 90, 158, 184, 210, 246, 288, 330, 334, 392, 450));
fennec_test_run(mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) * mat2x4(1, 2, 3, 4, 5, 6, 7, 8), mat2x3(70, 80, 90, 158, 184, 210)); fennec_test_spacer(1);
fennec_test_run(mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) * mat3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), mat3x3(70, 80, 90, 158, 184, 210, 246, 288, 330));
fennec_test_run(mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) * mat4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), mat4x3(70, 80, 90, 158, 184, 210, 246, 288, 330, 334, 392, 450));
fennec_test_spacer(1); fennec_test_run(mat4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16) * mat2x4(1, 2, 3, 4, 5, 6, 7, 8), mat2x4(90, 100, 110, 120, 202, 228, 254, 280));
fennec_test_run(mat4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16) * mat3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), mat3x4(90, 100, 110, 120, 202, 228, 254, 280, 314,356,398,440));
fennec_test_run(mat4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16) * mat4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), mat4x4(90, 100, 110, 120, 202, 228, 254, 280, 314, 356, 398, 440, 426, 484, 542, 600));
fennec_test_run(mat4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16) * mat2x4(1, 2, 3, 4, 5, 6, 7, 8), mat2x4(90, 100, 110, 120, 202, 228, 254, 280)); fennec_test_spacer(2);
fennec_test_run(mat4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16) * mat3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), mat3x4(90, 100, 110, 120, 202, 228, 254, 280, 314,356,398,440));
fennec_test_run(mat4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16) * mat4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), mat4x4(90, 100, 110, 120, 202, 228, 254, 280, 314, 356, 398, 440, 426, 484, 542, 600));
fennec_test_spacer(2);
fennec_test_section("matrixCompMult");
fennec_test_section("matrixCompMult"); fennec_test_spacer(1);
fennec_test_spacer(1); fennec_test_run(fennec::matrixCompMult(mat2(1, 2, 3, 4), mat2(1)), mat2(1, 0, 0, 4));
fennec_test_run(fennec::matrixCompMult(mat3(1, 4, 8, 6, 2, 5, 9, 7, 3), mat3(1)), mat3(1, 0, 0, 0, 2, 0, 0, 0, 3));
fennec_test_run(fennec::matrixCompMult(mat4(2, 1, -3, 4, -1, 0, 2, 5, 3, 2, 1, 0, 4, -2, 3, 1), mat4(1)), mat4(2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1));
fennec_test_run(fennec::matrixCompMult(mat2(1, 2, 3, 4), mat2(1)), mat2(1, 0, 0, 4)); fennec_test_spacer(2);
fennec_test_run(fennec::matrixCompMult(mat3(1, 4, 8, 6, 2, 5, 9, 7, 3), mat3(1)), mat3(1, 0, 0, 0, 2, 0, 0, 0, 3));
fennec_test_run(fennec::matrixCompMult(mat4(2, 1, -3, 4, -1, 0, 2, 5, 3, 2, 1, 0, 4, -2, 3, 1), mat4(1)), mat4(2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1));
fennec_test_spacer(2);
fennec_test_section("outerProduct");
fennec_test_section("outerProduct"); fennec_test_spacer(1);
fennec_test_spacer(1); fennec_test_run(fennec::outerProduct(vec2(1, 2), vec2(3, 4)), mat2(3, 6, 4, 8));
fennec_test_run(fennec::outerProduct(vec3(1, 2, 3), vec3(4, 5, 6)), mat3(4, 8, 12, 5, 10, 15, 6, 12, 18));
fennec_test_run(fennec::outerProduct(vec4(1, 2, 3, 4), vec4(5, 6, 7, 8)), mat4(5, 10, 15, 20, 6, 12, 18, 24, 7, 14, 21, 28, 8, 16, 24, 32));
fennec_test_run(fennec::outerProduct(vec2(1, 2), vec2(3, 4)), mat2(3, 6, 4, 8)); fennec_test_spacer(1);
fennec_test_run(fennec::outerProduct(vec3(1, 2, 3), vec3(4, 5, 6)), mat3(4, 8, 12, 5, 10, 15, 6, 12, 18));
fennec_test_run(fennec::outerProduct(vec4(1, 2, 3, 4), vec4(5, 6, 7, 8)), mat4(5, 10, 15, 20, 6, 12, 18, 24, 7, 14, 21, 28, 8, 16, 24, 32));
fennec_test_spacer(1); fennec_test_run(fennec::outerProduct(vec3(1, 2, 3), vec2(4, 5)), mat2x3(4, 8, 12, 5, 10, 15));
fennec_test_run(fennec::outerProduct(vec2(1, 2), vec3(3, 4, 5)), mat3x2(3, 6, 4, 8, 5, 10));
fennec_test_run(fennec::outerProduct(vec3(1, 2, 3), vec2(4, 5)), mat2x3(4, 8, 12, 5, 10, 15)); fennec_test_spacer(1);
fennec_test_run(fennec::outerProduct(vec2(1, 2), vec3(3, 4, 5)), mat3x2(3, 6, 4, 8, 5, 10));
fennec_test_spacer(1); fennec_test_run(fennec::outerProduct(vec4(1, 2, 3, 4), vec2(5, 6)), mat2x4(5, 10, 15, 20, 6, 12, 18, 24));
fennec_test_run(fennec::outerProduct(vec2(1, 2), vec4(3, 4, 5, 6)), mat4x2(3, 6, 4, 8, 5, 10, 6, 12));
fennec_test_run(fennec::outerProduct(vec4(1, 2, 3, 4), vec2(5, 6)), mat2x4(5, 10, 15, 20, 6, 12, 18, 24)); fennec_test_spacer(1);
fennec_test_run(fennec::outerProduct(vec2(1, 2), vec4(3, 4, 5, 6)), mat4x2(3, 6, 4, 8, 5, 10, 6, 12));
fennec_test_spacer(1); fennec_test_run(fennec::outerProduct(vec4(1, 2, 3, 4), vec3(5, 6, 7)), mat3x4(5, 10, 15, 20, 6, 12, 18, 24, 7, 14, 21, 28));
fennec_test_run(fennec::outerProduct(vec3(1, 2, 3), vec4(4, 5, 6, 7)), mat4x3(4, 8, 12, 5, 10, 15, 6, 12, 18, 7, 14, 21));
fennec_test_run(fennec::outerProduct(vec4(1, 2, 3, 4), vec3(5, 6, 7)), mat3x4(5, 10, 15, 20, 6, 12, 18, 24, 7, 14, 21, 28)); fennec_test_spacer(2);
fennec_test_run(fennec::outerProduct(vec3(1, 2, 3), vec4(4, 5, 6, 7)), mat4x3(4, 8, 12, 5, 10, 15, 6, 12, 18, 7, 14, 21));
fennec_test_spacer(2);
fennec_test_section("transpose");
fennec_test_section("transpose"); fennec_test_spacer(1);
fennec_test_spacer(1); fennec_test_run(fennec::transpose(mat2(1, 2, 3, 4)), mat2(1, 3, 2, 4));
fennec_test_run(fennec::transpose(mat3(1, 2, 3, 4, 5, 6, 7, 8, 9)), mat3(1, 4, 7, 2, 5, 8, 3, 6, 9));
fennec_test_run(fennec::transpose(mat4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)), mat4(1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16));
fennec_test_run(fennec::transpose(mat2(1, 2, 3, 4)), mat2(1, 3, 2, 4)); fennec_test_spacer(1);
fennec_test_run(fennec::transpose(mat3(1, 2, 3, 4, 5, 6, 7, 8, 9)), mat3(1, 4, 7, 2, 5, 8, 3, 6, 9));
fennec_test_run(fennec::transpose(mat4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)), mat4(1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16));
fennec_test_spacer(1); fennec_test_run(fennec::transpose(mat3x2(1, 2, 3, 4, 5, 6)), mat2x3(1, 3, 5, 2, 4, 6));
fennec_test_run(fennec::transpose(mat2x3(1, 2, 3, 4, 5, 6)), mat3x2(1, 4, 2, 5, 3, 6));
fennec_test_run(fennec::transpose(mat3x2(1, 2, 3, 4, 5, 6)), mat2x3(1, 3, 5, 2, 4, 6)); fennec_test_spacer(1);
fennec_test_run(fennec::transpose(mat2x3(1, 2, 3, 4, 5, 6)), mat3x2(1, 4, 2, 5, 3, 6));
fennec_test_spacer(1); fennec_test_run(fennec::transpose(mat4x2(1, 2, 3, 4, 5, 6, 7, 8)), mat2x4(1, 3, 5, 7, 2, 4, 6, 8));
fennec_test_run(fennec::transpose(mat2x4(1, 2, 3, 4, 5, 6, 7, 8)), mat4x2(1, 5, 2, 6, 3, 7, 4, 8));
fennec_test_run(fennec::transpose(mat4x2(1, 2, 3, 4, 5, 6, 7, 8)), mat2x4(1, 3, 5, 7, 2, 4, 6, 8)); fennec_test_spacer(1);
fennec_test_run(fennec::transpose(mat2x4(1, 2, 3, 4, 5, 6, 7, 8)), mat4x2(1, 5, 2, 6, 3, 7, 4, 8));
fennec_test_spacer(1); fennec_test_run(fennec::transpose(mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)), mat3x4(1, 4, 7, 10, 2, 5, 8, 11, 3, 6, 9, 12));
fennec_test_run(fennec::transpose(mat3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)), mat4x3(1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12));
fennec_test_run(fennec::transpose(mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)), mat3x4(1, 4, 7, 10, 2, 5, 8, 11, 3, 6, 9, 12)); fennec_test_spacer(2);
fennec_test_run(fennec::transpose(mat3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)), mat4x3(1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12));
fennec_test_spacer(2);
fennec_test_section("determinant");
fennec_test_section("determinant"); fennec_test_spacer(1);
fennec_test_spacer(1); fennec_test_run(fennec::determinant(mat2(1, 2, 3, 4)), -2.0f);
fennec_test_run(fennec::determinant(mat3(1, 4, 8, 6, 2, 5, 9, 7, 3)), 271.0f);
fennec_test_run(fennec::determinant(mat4(2, 1, -3, 4, -1, 0, 2, 5, 3, 2, 1, 0, 4, -2, 3, 1)), 414.0f);
fennec_test_run(fennec::determinant(mat2(1, 2, 3, 4)), -2.0f); fennec_test_spacer(2);
fennec_test_run(fennec::determinant(mat3(1, 4, 8, 6, 2, 5, 9, 7, 3)), 271.0f);
fennec_test_run(fennec::determinant(mat4(2, 1, -3, 4, -1, 0, 2, 5, 3, 2, 1, 0, 4, -2, 3, 1)), 414.0f);
fennec_test_spacer(2);
fennec_test_section("inverse");
fennec_test_section("inverse"); fennec_test_spacer(1);
fennec_test_spacer(1); fennec_test_run(fennec::inverse(mat2(1, 2, 3, 4)), mat2(-2, 1, 1.5, -0.5));
fennec_test_run(fennec::inverse(mat3(1, 2, 3, 0, 1, 4, 5, 6, 0)), mat3(-24, 18, 5, 20, -15, -4, -5, 4, 1));
fennec_test_run(fennec::inverse(mat2(1, 2, 3, 4)), mat2(-2, 1, 1.5, -0.5)); fennec_test_run(fennec::inverse(mat4(2, 1, -3, 4, -1, 0, 2, 5, 3, 2, 1, 0, 4, -2, 3, 1)), (1.0f / 414.0f) * mat4(36, -39, 33, 51, -18, 31, 133, -83, -72, 55, 49, 13, 36, 53, -13, 5));
fennec_test_run(fennec::inverse(mat3(1, 2, 3, 0, 1, 4, 5, 6, 0)), mat3(-24, 18, 5, 20, -15, -4, -5, 4, 1)); }
fennec_test_run(fennec::inverse(mat4(2, 1, -3, 4, -1, 0, 2, 5, 3, 2, 1, 0, 4, -2, 3, 1)), (1.0f / 414.0f) * mat4(36, -39, 33, 51, -18, 31, 133, -83, -72, 55, 49, 13, 36, 53, -13, 5));
}
}
} }

View File

@@ -20,34 +20,29 @@
#define FENNEC_TEST_MATH_RELATIONAL_H #define FENNEC_TEST_MATH_RELATIONAL_H
#include "../../test.h" #include "../../test.h"
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_math_relational()
{ {
fennec_test_run(fennec::lessThan(vec3(3, 2, 1), vec3(1, 2, 3)), bvec3(false, false, true));
fennec_test_run(fennec::lessThanEqual(vec3(3, 2, 1), vec3(1, 2, 3)), bvec3(false, true, true));
inline void fennec_test_math_relational() fennec_test_spacer(1);
{
fennec_test_run(fennec::lessThan(vec3(3, 2, 1), vec3(1, 2, 3)), bvec3(false, false, true));
fennec_test_run(fennec::lessThanEqual(vec3(3, 2, 1), vec3(1, 2, 3)), bvec3(false, true, true));
fennec_test_spacer(1); fennec_test_run(fennec::greaterThan(vec3(3, 2, 1), vec3(1, 2, 3)), bvec3(true, false, false));
fennec_test_run(fennec::greaterThanEqual(vec3(3, 2, 1), vec3(1, 2, 3)), bvec3(true, true, false));
fennec_test_run(fennec::greaterThan(vec3(3, 2, 1), vec3(1, 2, 3)), bvec3(true, false, false)); fennec_test_spacer(1);
fennec_test_run(fennec::greaterThanEqual(vec3(3, 2, 1), vec3(1, 2, 3)), bvec3(true, true, false));
fennec_test_spacer(1); fennec_test_run(fennec::equal(vec3(3, 2, 1), vec3(1, 2, 3)), bvec3(false, true, false));
fennec_test_run(fennec::notEqual(vec3(3, 2, 1), vec3(1, 2, 3)), bvec3(true, false, true));
fennec_test_run(fennec::equal(vec3(3, 2, 1), vec3(1, 2, 3)), bvec3(false, true, false)); fennec_test_spacer(1);
fennec_test_run(fennec::notEqual(vec3(3, 2, 1), vec3(1, 2, 3)), bvec3(true, false, true));
fennec_test_spacer(1); fennec_test_run(not(bvec3(true, false, true)), bvec3(false, true, false));
fennec_test_run(fennec::all(bvec3(true, true, true)), true);
fennec_test_run(not(bvec3(true, false, true)), bvec3(false, true, false)); }
fennec_test_run(fennec::all(bvec3(true, true, true)), true);
}
}
} }

View File

@@ -24,50 +24,45 @@
#include "../../test.h" #include "../../test.h"
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_math_scalar()
{ {
fennec_test_section("component_count");
inline void fennec_test_math_scalar() fennec_test_spacer(1);
{
fennec_test_section("component_count");
fennec_test_spacer(1); fennec_test_run((component_count_v<bool_t> == 1), true);
fennec_test_run((component_count_v<int_t> == 1), true);
fennec_test_run((component_count_v<uint_t> == 1), true);
fennec_test_run((component_count_v<float_t> == 1), true);
fennec_test_run((component_count_v<double_t> == 1), true);
fennec_test_run((component_count_v<bool_t> == 1), true); fennec_test_spacer(1);
fennec_test_run((component_count_v<int_t> == 1), true);
fennec_test_run((component_count_v<uint_t> == 1), true);
fennec_test_run((component_count_v<float_t> == 1), true);
fennec_test_run((component_count_v<double_t> == 1), true);
fennec_test_spacer(1); fennec_test_run((component_count_v<const bool_t> == 1), true);
fennec_test_run((component_count_v<const int_t> == 1), true);
fennec_test_run((component_count_v<const uint_t> == 1), true);
fennec_test_run((component_count_v<const float_t> == 1), true);
fennec_test_run((component_count_v<const double_t> == 1), true);
fennec_test_run((component_count_v<const bool_t> == 1), true); fennec_test_spacer(1);
fennec_test_run((component_count_v<const int_t> == 1), true);
fennec_test_run((component_count_v<const uint_t> == 1), true);
fennec_test_run((component_count_v<const float_t> == 1), true);
fennec_test_run((component_count_v<const double_t> == 1), true);
fennec_test_spacer(1); fennec_test_run((component_count_v<volatile bool_t> == 1), true);
fennec_test_run((component_count_v<volatile int_t> == 1), true);
fennec_test_run((component_count_v<volatile uint_t> == 1), true);
fennec_test_run((component_count_v<volatile float_t> == 1), true);
fennec_test_run((component_count_v<volatile double_t> == 1), true);
fennec_test_run((component_count_v<volatile bool_t> == 1), true); fennec_test_spacer(1);
fennec_test_run((component_count_v<volatile int_t> == 1), true);
fennec_test_run((component_count_v<volatile uint_t> == 1), true);
fennec_test_run((component_count_v<volatile float_t> == 1), true);
fennec_test_run((component_count_v<volatile double_t> == 1), true);
fennec_test_spacer(1); fennec_test_run((component_count_v<const volatile bool_t> == 1), true);
fennec_test_run((component_count_v<const volatile int_t> == 1), true);
fennec_test_run((component_count_v<const volatile bool_t> == 1), true); fennec_test_run((component_count_v<const volatile uint_t> == 1), true);
fennec_test_run((component_count_v<const volatile int_t> == 1), true); fennec_test_run((component_count_v<const volatile float_t> == 1), true);
fennec_test_run((component_count_v<const volatile uint_t> == 1), true); fennec_test_run((component_count_v<const volatile double_t> == 1), true);
fennec_test_run((component_count_v<const volatile float_t> == 1), true); }
fennec_test_run((component_count_v<const volatile double_t> == 1), true);
}
}
} }

View File

@@ -23,98 +23,93 @@
#include "../../test.h" #include "../../test.h"
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_math_trigonometric()
{ {
fennec_test_section("angle conversions");
inline void fennec_test_math_trigonometric() fennec_test_spacer(1);
{
fennec_test_section("angle conversions");
fennec_test_spacer(1); fennec_test_run(fennec::radians( 45.0f), fennec::quarter_pi<float>());
fennec_test_run(fennec::radians( 90.0f), fennec::half_pi<float>());
fennec_test_run(fennec::radians(180.0f), fennec::pi<float>());
fennec_test_run(fennec::radians(270.0f), fennec::three_halves_pi<float>());
fennec_test_run(fennec::radians(360.0f), fennec::two_pi<float>());
fennec_test_run(fennec::radians( 45.0f), fennec::quarter_pi<float>()); fennec_test_spacer(1);
fennec_test_run(fennec::radians( 90.0f), fennec::half_pi<float>());
fennec_test_run(fennec::radians(180.0f), fennec::pi<float>());
fennec_test_run(fennec::radians(270.0f), fennec::three_halves_pi<float>());
fennec_test_run(fennec::radians(360.0f), fennec::two_pi<float>());
fennec_test_spacer(1); fennec_test_run(fennec::degrees(fennec::quarter_pi<float>()), 45.0f);
fennec_test_run(fennec::degrees(fennec::half_pi<float>()), 90.0f);
fennec_test_run(fennec::degrees(fennec::pi<float>()), 180.0f);
fennec_test_run(fennec::degrees(fennec::three_halves_pi<float>()), 270.0f);
fennec_test_run(fennec::degrees(fennec::two_pi<float>()), 360.0f);
fennec_test_run(fennec::degrees(fennec::quarter_pi<float>()), 45.0f); fennec_test_spacer(2);
fennec_test_run(fennec::degrees(fennec::half_pi<float>()), 90.0f);
fennec_test_run(fennec::degrees(fennec::pi<float>()), 180.0f);
fennec_test_run(fennec::degrees(fennec::three_halves_pi<float>()), 270.0f);
fennec_test_run(fennec::degrees(fennec::two_pi<float>()), 360.0f);
fennec_test_spacer(2);
fennec_test_section("trig functions"); fennec_test_section("trig functions");
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(fennec::sin(fennec::sixth_pi<float>()), one_half<float>()); fennec_test_run(fennec::sin(fennec::sixth_pi<float>()), one_half<float>());
fennec_test_run(fennec::cos(fennec::sixth_pi<float>()), sqrt_three<float>() / 2.0f); fennec_test_run(fennec::cos(fennec::sixth_pi<float>()), sqrt_three<float>() / 2.0f);
fennec_test_run(fennec::tan(fennec::sixth_pi<float>()), sqrt_three<float>() / 3.0f); fennec_test_run(fennec::tan(fennec::sixth_pi<float>()), sqrt_three<float>() / 3.0f);
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(fennec::asin(one_half<float>()), fennec::sixth_pi<float>()); fennec_test_run(fennec::asin(one_half<float>()), fennec::sixth_pi<float>());
fennec_test_run(fennec::acos(sqrt_three<float>() / 2.0f), fennec::sixth_pi<float>()); fennec_test_run(fennec::acos(sqrt_three<float>() / 2.0f), fennec::sixth_pi<float>());
fennec_test_run(fennec::atan(sqrt_three<float>() / 3.0f), fennec::sixth_pi<float>()); fennec_test_run(fennec::atan(sqrt_three<float>() / 3.0f), fennec::sixth_pi<float>());
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_run(fennec::sin(fennec::quarter_pi<float>()), sqrt_two<float>() / 2.0f); fennec_test_run(fennec::sin(fennec::quarter_pi<float>()), sqrt_two<float>() / 2.0f);
fennec_test_run(fennec::cos(fennec::quarter_pi<float>()), sqrt_two<float>() / 2.0f); fennec_test_run(fennec::cos(fennec::quarter_pi<float>()), sqrt_two<float>() / 2.0f);
fennec_test_run(fennec::tan(fennec::quarter_pi<float>()), 1.0f); fennec_test_run(fennec::tan(fennec::quarter_pi<float>()), 1.0f);
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(fennec::asin(sqrt_two<float>() / 2.0f), fennec::quarter_pi<float>()); fennec_test_run(fennec::asin(sqrt_two<float>() / 2.0f), fennec::quarter_pi<float>());
fennec_test_run(fennec::acos(sqrt_two<float>() / 2.0f), fennec::quarter_pi<float>()); fennec_test_run(fennec::acos(sqrt_two<float>() / 2.0f), fennec::quarter_pi<float>());
fennec_test_run(fennec::atan(1.0f), fennec::quarter_pi<float>()); fennec_test_run(fennec::atan(1.0f), fennec::quarter_pi<float>());
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_section("hyperbolic functions"); fennec_test_section("hyperbolic functions");
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(fennec::sinh(0.0f), 0.0f); fennec_test_run(fennec::sinh(0.0f), 0.0f);
fennec_test_run(fennec::cosh(0.0f), 1.0f); fennec_test_run(fennec::cosh(0.0f), 1.0f);
fennec_test_run(fennec::tanh(0.0f), 0.0f); fennec_test_run(fennec::tanh(0.0f), 0.0f);
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(fennec::asinh(0.0f), 0.0f); fennec_test_run(fennec::asinh(0.0f), 0.0f);
fennec_test_run(fennec::acosh(1.0f), 0.0f); fennec_test_run(fennec::acosh(1.0f), 0.0f);
fennec_test_run(fennec::atanh(0.0f), 0.0f); fennec_test_run(fennec::atanh(0.0f), 0.0f);
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_run(fennec::sinh(1.0f), (fennec::e<float>() - fennec::one_over_e<float>()) / 2.0f); fennec_test_run(fennec::sinh(1.0f), (fennec::e<float>() - fennec::one_over_e<float>()) / 2.0f);
fennec_test_run(fennec::cosh(1.0f), (fennec::e<float>() + fennec::one_over_e<float>()) / 2.0f); fennec_test_run(fennec::cosh(1.0f), (fennec::e<float>() + fennec::one_over_e<float>()) / 2.0f);
fennec_test_run(fennec::tanh(1.0f), ((fennec::e_raised_two<float>() - 1) / (fennec::e_raised_two<float>() + 1))); fennec_test_run(fennec::tanh(1.0f), ((fennec::e_raised_two<float>() - 1) / (fennec::e_raised_two<float>() + 1)));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(fennec::asinh((fennec::e<float>() - fennec::one_over_e<float>()) / 2.0f), 1.0f); fennec_test_run(fennec::asinh((fennec::e<float>() - fennec::one_over_e<float>()) / 2.0f), 1.0f);
fennec_test_run(fennec::acosh((fennec::e<float>() + fennec::one_over_e<float>()) / 2.0f), 1.0f); fennec_test_run(fennec::acosh((fennec::e<float>() + fennec::one_over_e<float>()) / 2.0f), 1.0f);
fennec_test_run(fennec::atanh(((fennec::e_raised_two<float>() - 1) / (fennec::e_raised_two<float>() + 1))), 1.0f); fennec_test_run(fennec::atanh(((fennec::e_raised_two<float>() - 1) / (fennec::e_raised_two<float>() + 1))), 1.0f);
} }
}
} }

View File

@@ -26,577 +26,572 @@
#include "../../test.h" #include "../../test.h"
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_math_vector()
{ {
fennec_test_section("component_count");
inline void fennec_test_math_vector()
{ fennec_test_spacer(1);
fennec_test_section("component_count");
fennec_test_run((component_count_v<bvec2> == 2), true);
fennec_test_spacer(1); fennec_test_run((component_count_v<bvec3> == 3), true);
fennec_test_run((component_count_v<bvec4> == 4), true);
fennec_test_run((component_count_v<bvec2> == 2), true); fennec_test_run((component_count_v<bvec2&> == 2), true);
fennec_test_run((component_count_v<bvec3> == 3), true); fennec_test_run((component_count_v<bvec3&> == 3), true);
fennec_test_run((component_count_v<bvec4> == 4), true); fennec_test_run((component_count_v<bvec4&> == 4), true);
fennec_test_run((component_count_v<bvec2&> == 2), true); fennec_test_run((component_count_v<bvec2&&> == 2), true);
fennec_test_run((component_count_v<bvec3&> == 3), true); fennec_test_run((component_count_v<bvec3&&> == 3), true);
fennec_test_run((component_count_v<bvec4&> == 4), true); fennec_test_run((component_count_v<bvec4&&> == 4), true);
fennec_test_run((component_count_v<bvec2&&> == 2), true); fennec_test_run((component_count_v<const bvec2&> == 2), true);
fennec_test_run((component_count_v<bvec3&&> == 3), true); fennec_test_run((component_count_v<const bvec3&> == 3), true);
fennec_test_run((component_count_v<bvec4&&> == 4), true); fennec_test_run((component_count_v<const bvec4&> == 4), true);
fennec_test_run((component_count_v<const bvec2&> == 2), true);
fennec_test_run((component_count_v<const bvec3&> == 3), true); fennec_test_spacer(1);
fennec_test_run((component_count_v<const bvec4&> == 4), true);
fennec_test_run((component_count_v<ivec2> == 2), true);
fennec_test_spacer(1); fennec_test_run((component_count_v<ivec3> == 3), true);
fennec_test_run((component_count_v<ivec4> == 4), true);
fennec_test_run((component_count_v<ivec2> == 2), true); fennec_test_run((component_count_v<ivec2&> == 2), true);
fennec_test_run((component_count_v<ivec3> == 3), true); fennec_test_run((component_count_v<ivec3&> == 3), true);
fennec_test_run((component_count_v<ivec4> == 4), true); fennec_test_run((component_count_v<ivec4&> == 4), true);
fennec_test_run((component_count_v<ivec2&> == 2), true); fennec_test_run((component_count_v<ivec2&&> == 2), true);
fennec_test_run((component_count_v<ivec3&> == 3), true); fennec_test_run((component_count_v<ivec3&&> == 3), true);
fennec_test_run((component_count_v<ivec4&> == 4), true); fennec_test_run((component_count_v<ivec4&&> == 4), true);
fennec_test_run((component_count_v<ivec2&&> == 2), true); fennec_test_run((component_count_v<const ivec2&> == 2), true);
fennec_test_run((component_count_v<ivec3&&> == 3), true); fennec_test_run((component_count_v<const ivec3&> == 3), true);
fennec_test_run((component_count_v<ivec4&&> == 4), true); fennec_test_run((component_count_v<const ivec4&> == 4), true);
fennec_test_run((component_count_v<const ivec2&> == 2), true);
fennec_test_run((component_count_v<const ivec3&> == 3), true);
fennec_test_run((component_count_v<const ivec4&> == 4), true);
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run((component_count_v<uvec2> == 2), true); fennec_test_run((component_count_v<uvec2> == 2), true);
fennec_test_run((component_count_v<uvec3> == 3), true); fennec_test_run((component_count_v<uvec3> == 3), true);
fennec_test_run((component_count_v<uvec4> == 4), true); fennec_test_run((component_count_v<uvec4> == 4), true);
fennec_test_run((component_count_v<uvec2&> == 2), true); fennec_test_run((component_count_v<uvec2&> == 2), true);
fennec_test_run((component_count_v<uvec3&> == 3), true); fennec_test_run((component_count_v<uvec3&> == 3), true);
fennec_test_run((component_count_v<uvec4&> == 4), true); fennec_test_run((component_count_v<uvec4&> == 4), true);
fennec_test_run((component_count_v<uvec2&&> == 2), true); fennec_test_run((component_count_v<uvec2&&> == 2), true);
fennec_test_run((component_count_v<uvec3&&> == 3), true); fennec_test_run((component_count_v<uvec3&&> == 3), true);
fennec_test_run((component_count_v<uvec4&&> == 4), true); fennec_test_run((component_count_v<uvec4&&> == 4), true);
fennec_test_run((component_count_v<const uvec2&> == 2), true); fennec_test_run((component_count_v<const uvec2&> == 2), true);
fennec_test_run((component_count_v<const uvec3&> == 3), true); fennec_test_run((component_count_v<const uvec3&> == 3), true);
fennec_test_run((component_count_v<const uvec4&> == 4), true); fennec_test_run((component_count_v<const uvec4&> == 4), true);
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run((component_count_v<vec2> == 2), true); fennec_test_run((component_count_v<vec2> == 2), true);
fennec_test_run((component_count_v<vec3> == 3), true); fennec_test_run((component_count_v<vec3> == 3), true);
fennec_test_run((component_count_v<vec4> == 4), true); fennec_test_run((component_count_v<vec4> == 4), true);
fennec_test_run((component_count_v<vec2&> == 2), true); fennec_test_run((component_count_v<vec2&> == 2), true);
fennec_test_run((component_count_v<vec3&> == 3), true); fennec_test_run((component_count_v<vec3&> == 3), true);
fennec_test_run((component_count_v<vec4&> == 4), true); fennec_test_run((component_count_v<vec4&> == 4), true);
fennec_test_run((component_count_v<vec2&&> == 2), true); fennec_test_run((component_count_v<vec2&&> == 2), true);
fennec_test_run((component_count_v<vec3&&> == 3), true); fennec_test_run((component_count_v<vec3&&> == 3), true);
fennec_test_run((component_count_v<vec4&&> == 4), true); fennec_test_run((component_count_v<vec4&&> == 4), true);
fennec_test_run((component_count_v<const vec2&> == 2), true); fennec_test_run((component_count_v<const vec2&> == 2), true);
fennec_test_run((component_count_v<const vec3&> == 3), true); fennec_test_run((component_count_v<const vec3&> == 3), true);
fennec_test_run((component_count_v<const vec4&> == 4), true); fennec_test_run((component_count_v<const vec4&> == 4), true);
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run((component_count_v<dvec2> == 2), true); fennec_test_run((component_count_v<dvec2> == 2), true);
fennec_test_run((component_count_v<dvec3> == 3), true); fennec_test_run((component_count_v<dvec3> == 3), true);
fennec_test_run((component_count_v<dvec4> == 4), true); fennec_test_run((component_count_v<dvec4> == 4), true);
fennec_test_run((component_count_v<dvec2&> == 2), true); fennec_test_run((component_count_v<dvec2&> == 2), true);
fennec_test_run((component_count_v<dvec3&> == 3), true); fennec_test_run((component_count_v<dvec3&> == 3), true);
fennec_test_run((component_count_v<dvec4&> == 4), true); fennec_test_run((component_count_v<dvec4&> == 4), true);
fennec_test_run((component_count_v<dvec2&&> == 2), true); fennec_test_run((component_count_v<dvec2&&> == 2), true);
fennec_test_run((component_count_v<dvec3&&> == 3), true); fennec_test_run((component_count_v<dvec3&&> == 3), true);
fennec_test_run((component_count_v<dvec4&&> == 4), true); fennec_test_run((component_count_v<dvec4&&> == 4), true);
fennec_test_run((component_count_v<const dvec2&> == 2), true); fennec_test_run((component_count_v<const dvec2&> == 2), true);
fennec_test_run((component_count_v<const dvec3&> == 3), true); fennec_test_run((component_count_v<const dvec3&> == 3), true);
fennec_test_run((component_count_v<const dvec4&> == 4), true); fennec_test_run((component_count_v<const dvec4&> == 4), true);
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_section("vec2 equivalency operator"); fennec_test_section("vec2 equivalency operator");
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run((vec2() == vec2()), true); fennec_test_run((vec2() == vec2()), true);
fennec_test_run((vec2() != vec2()), false); fennec_test_run((vec2() != vec2()), false);
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_section("vec2 constructors"); fennec_test_section("vec2 constructors");
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(vec2(), vec2(0.0f, 0.0f)); fennec_test_run(vec2(), vec2(0.0f, 0.0f));
fennec_test_run(vec2(1.0f), vec2(1.0f, 1.0f)); fennec_test_run(vec2(1.0f), vec2(1.0f, 1.0f));
fennec_test_run(vec2(), vec2(0.0, 0.0)); fennec_test_run(vec2(), vec2(0.0, 0.0));
fennec_test_run(vec2(1.0), vec2(1.0, 1.0)); fennec_test_run(vec2(1.0), vec2(1.0, 1.0));
fennec_test_run(vec2(), vec2(0, 0)); fennec_test_run(vec2(), vec2(0, 0));
fennec_test_run(vec2(1), vec2(1, 1)); fennec_test_run(vec2(1), vec2(1, 1));
fennec_test_run(vec2(fennec::copy(vec2(1.0f))), vec2(1.0f)); fennec_test_run(vec2(fennec::copy(vec2(1.0f))), vec2(1.0f));
fennec_test_run(vec2(fennec::move(vec2(1.0f))), vec2(1.0f)); fennec_test_run(vec2(fennec::move(vec2(1.0f))), vec2(1.0f));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_section("vec2 swizzles"); fennec_test_section("vec2 swizzles");
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(vec2(vec2(0, 1).xx), vec2(0, 0)); fennec_test_run(vec2(vec2(0, 1).xx), vec2(0, 0));
fennec_test_run(vec2(vec2(0, 1).xy), vec2(0, 1)); fennec_test_run(vec2(vec2(0, 1).xy), vec2(0, 1));
fennec_test_run(vec2(vec2(0, 1).yx), vec2(1, 0)); fennec_test_run(vec2(vec2(0, 1).yx), vec2(1, 0));
fennec_test_run(vec2(vec2(0, 1).yy), vec2(1, 1)); fennec_test_run(vec2(vec2(0, 1).yy), vec2(1, 1));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_section("vec3 constructors"); fennec_test_section("vec3 constructors");
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(vec3(), vec3(0.0f, 0.0f, 0.0f)); fennec_test_run(vec3(), vec3(0.0f, 0.0f, 0.0f));
fennec_test_run(vec3(1.0f), vec3(1.0f, 1.0f, 1.0f)); fennec_test_run(vec3(1.0f), vec3(1.0f, 1.0f, 1.0f));
fennec_test_run(vec3(), vec3(0.0, 0.0, 0.0)); fennec_test_run(vec3(), vec3(0.0, 0.0, 0.0));
fennec_test_run(vec3(1.0), vec3(1.0, 1.0, 1.0)); fennec_test_run(vec3(1.0), vec3(1.0, 1.0, 1.0));
fennec_test_run(vec3(), vec3(0, 0, 0)); fennec_test_run(vec3(), vec3(0, 0, 0));
fennec_test_run(vec3(1), vec3(1, 1, 1)); fennec_test_run(vec3(1), vec3(1, 1, 1));
fennec_test_run(vec3(fennec::copy(vec3(1))), vec3(1)); fennec_test_run(vec3(fennec::copy(vec3(1))), vec3(1));
fennec_test_run(vec3(fennec::move(vec3(1))), vec3(1)); fennec_test_run(vec3(fennec::move(vec3(1))), vec3(1));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_section("vec3 swizzles"); fennec_test_section("vec3 swizzles");
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(vec3(vec3(0, 1, 2).xxx), vec3(0, 0, 0)); fennec_test_run(vec3(vec3(0, 1, 2).xxx), vec3(0, 0, 0));
fennec_test_run(vec3(vec3(0, 1, 2).xxy), vec3(0, 0, 1)); fennec_test_run(vec3(vec3(0, 1, 2).xxy), vec3(0, 0, 1));
fennec_test_run(vec3(vec3(0, 1, 2).xxz), vec3(0, 0, 2)); fennec_test_run(vec3(vec3(0, 1, 2).xxz), vec3(0, 0, 2));
fennec_test_run(vec3(vec3(0, 1, 2).xyx), vec3(0, 1, 0)); fennec_test_run(vec3(vec3(0, 1, 2).xyx), vec3(0, 1, 0));
fennec_test_run(vec3(vec3(0, 1, 2).xyy), vec3(0, 1, 1)); fennec_test_run(vec3(vec3(0, 1, 2).xyy), vec3(0, 1, 1));
fennec_test_run(vec3(vec3(0, 1, 2).xyz), vec3(0, 1, 2)); fennec_test_run(vec3(vec3(0, 1, 2).xyz), vec3(0, 1, 2));
fennec_test_run(vec3(vec3(0, 1, 2).xzx), vec3(0, 2, 0)); fennec_test_run(vec3(vec3(0, 1, 2).xzx), vec3(0, 2, 0));
fennec_test_run(vec3(vec3(0, 1, 2).xzy), vec3(0, 2, 1)); fennec_test_run(vec3(vec3(0, 1, 2).xzy), vec3(0, 2, 1));
fennec_test_run(vec3(vec3(0, 1, 2).xzz), vec3(0, 2, 2)); fennec_test_run(vec3(vec3(0, 1, 2).xzz), vec3(0, 2, 2));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(vec3(vec3(0, 1, 2).yxx), vec3(1, 0, 0)); fennec_test_run(vec3(vec3(0, 1, 2).yxx), vec3(1, 0, 0));
fennec_test_run(vec3(vec3(0, 1, 2).yxy), vec3(1, 0, 1)); fennec_test_run(vec3(vec3(0, 1, 2).yxy), vec3(1, 0, 1));
fennec_test_run(vec3(vec3(0, 1, 2).yxz), vec3(1, 0, 2)); fennec_test_run(vec3(vec3(0, 1, 2).yxz), vec3(1, 0, 2));
fennec_test_run(vec3(vec3(0, 1, 2).yyx), vec3(1, 1, 0)); fennec_test_run(vec3(vec3(0, 1, 2).yyx), vec3(1, 1, 0));
fennec_test_run(vec3(vec3(0, 1, 2).yyy), vec3(1, 1, 1)); fennec_test_run(vec3(vec3(0, 1, 2).yyy), vec3(1, 1, 1));
fennec_test_run(vec3(vec3(0, 1, 2).yyz), vec3(1, 1, 2)); fennec_test_run(vec3(vec3(0, 1, 2).yyz), vec3(1, 1, 2));
fennec_test_run(vec3(vec3(0, 1, 2).yzx), vec3(1, 2, 0)); fennec_test_run(vec3(vec3(0, 1, 2).yzx), vec3(1, 2, 0));
fennec_test_run(vec3(vec3(0, 1, 2).yzy), vec3(1, 2, 1)); fennec_test_run(vec3(vec3(0, 1, 2).yzy), vec3(1, 2, 1));
fennec_test_run(vec3(vec3(0, 1, 2).yzz), vec3(1, 2, 2)); fennec_test_run(vec3(vec3(0, 1, 2).yzz), vec3(1, 2, 2));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(vec3(vec3(0, 1, 2).zxx), vec3(2, 0, 0)); fennec_test_run(vec3(vec3(0, 1, 2).zxx), vec3(2, 0, 0));
fennec_test_run(vec3(vec3(0, 1, 2).zxy), vec3(2, 0, 1)); fennec_test_run(vec3(vec3(0, 1, 2).zxy), vec3(2, 0, 1));
fennec_test_run(vec3(vec3(0, 1, 2).zxz), vec3(2, 0, 2)); fennec_test_run(vec3(vec3(0, 1, 2).zxz), vec3(2, 0, 2));
fennec_test_run(vec3(vec3(0, 1, 2).zyx), vec3(2, 1, 0)); fennec_test_run(vec3(vec3(0, 1, 2).zyx), vec3(2, 1, 0));
fennec_test_run(vec3(vec3(0, 1, 2).zyy), vec3(2, 1, 1)); fennec_test_run(vec3(vec3(0, 1, 2).zyy), vec3(2, 1, 1));
fennec_test_run(vec3(vec3(0, 1, 2).zyz), vec3(2, 1, 2)); fennec_test_run(vec3(vec3(0, 1, 2).zyz), vec3(2, 1, 2));
fennec_test_run(vec3(vec3(0, 1, 2).zzx), vec3(2, 2, 0)); fennec_test_run(vec3(vec3(0, 1, 2).zzx), vec3(2, 2, 0));
fennec_test_run(vec3(vec3(0, 1, 2).zzy), vec3(2, 2, 1)); fennec_test_run(vec3(vec3(0, 1, 2).zzy), vec3(2, 2, 1));
fennec_test_run(vec3(vec3(0, 1, 2).zzz), vec3(2, 2, 2)); fennec_test_run(vec3(vec3(0, 1, 2).zzz), vec3(2, 2, 2));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_section("scalar-vector arithmetic operations"); fennec_test_section("scalar-vector arithmetic operations");
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(2.0 + vec2(1, 2), vec2(3, 4)); fennec_test_run(2.0 + vec2(1, 2), vec2(3, 4));
fennec_test_run(2.0 + vec3(1, 2, 3), vec3(3, 4, 5)); fennec_test_run(2.0 + vec3(1, 2, 3), vec3(3, 4, 5));
fennec_test_run(2.0 + vec4(1, 2, 3, 4), vec4(3, 4, 5, 6)); fennec_test_run(2.0 + vec4(1, 2, 3, 4), vec4(3, 4, 5, 6));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_run(2.0 - vec2(1, 2), vec2(1, 0)); fennec_test_run(2.0 - vec2(1, 2), vec2(1, 0));
fennec_test_run(2.0 - vec3(1, 2, 3), vec3(1, 0, -1)); fennec_test_run(2.0 - vec3(1, 2, 3), vec3(1, 0, -1));
fennec_test_run(2.0 - vec4(1, 2, 3, 4), vec4(1, 0, -1, -2)); fennec_test_run(2.0 - vec4(1, 2, 3, 4), vec4(1, 0, -1, -2));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_run(2.0 * vec2(1, 2), vec2(2, 4)); fennec_test_run(2.0 * vec2(1, 2), vec2(2, 4));
fennec_test_run(2.0 * vec3(1, 2, 3), vec3(2, 4, 6)); fennec_test_run(2.0 * vec3(1, 2, 3), vec3(2, 4, 6));
fennec_test_run(2.0 * vec4(1, 2, 3, 4), vec4(2, 4, 6, 8)); fennec_test_run(2.0 * vec4(1, 2, 3, 4), vec4(2, 4, 6, 8));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_run(2.0 / vec2(1, 2), vec2(2.0, 1.0)); fennec_test_run(2.0 / vec2(1, 2), vec2(2.0, 1.0));
fennec_test_run(2.0 / vec3(1, 2, 4), vec3(2.0, 1.0, 0.5)); fennec_test_run(2.0 / vec3(1, 2, 4), vec3(2.0, 1.0, 0.5));
fennec_test_run(2.0 / vec4(1, 2, 4, 8), vec4(2.0, 1.0, 0.5, 0.25)); fennec_test_run(2.0 / vec4(1, 2, 4, 8), vec4(2.0, 1.0, 0.5, 0.25));
fennec_test_run(2 % ivec2(1, 2), ivec2(0, 0)); fennec_test_run(2 % ivec2(1, 2), ivec2(0, 0));
fennec_test_run(2 % ivec3(1, 2, 3), ivec3(0, 0, 2)); fennec_test_run(2 % ivec3(1, 2, 3), ivec3(0, 0, 2));
fennec_test_run(2 % ivec4(1, 2, 3, 4), ivec4(0, 0, 2, 2)); fennec_test_run(2 % ivec4(1, 2, 3, 4), ivec4(0, 0, 2, 2));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_section("vector-scalar arithmetic operations"); fennec_test_section("vector-scalar arithmetic operations");
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(vec2(1, 2) + 2.0, vec2(3, 4)); fennec_test_run(vec2(1, 2) + 2.0, vec2(3, 4));
fennec_test_run(vec3(1, 2, 3) + 2.0, vec3(3, 4, 5)); fennec_test_run(vec3(1, 2, 3) + 2.0, vec3(3, 4, 5));
fennec_test_run(vec4(1, 2, 3, 4) + 2.0, vec4(3, 4, 5, 6)); fennec_test_run(vec4(1, 2, 3, 4) + 2.0, vec4(3, 4, 5, 6));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_run(vec2(1, 2) - 2.0, vec2(-1, 0)); fennec_test_run(vec2(1, 2) - 2.0, vec2(-1, 0));
fennec_test_run(vec3(1, 2, 3) - 2.0, vec3(-1, 0, 1)); fennec_test_run(vec3(1, 2, 3) - 2.0, vec3(-1, 0, 1));
fennec_test_run(vec4(1, 2, 3, 4) - 2.0, vec4(-1, 0, 1, 2)); fennec_test_run(vec4(1, 2, 3, 4) - 2.0, vec4(-1, 0, 1, 2));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_run(vec2(1, 2) * 2.0, vec2(2, 4)); fennec_test_run(vec2(1, 2) * 2.0, vec2(2, 4));
fennec_test_run(vec3(1, 2, 3) * 2.0, vec3(2, 4, 6)); fennec_test_run(vec3(1, 2, 3) * 2.0, vec3(2, 4, 6));
fennec_test_run(vec4(1, 2, 3, 4) * 2.0, vec4(2, 4, 6, 8)); fennec_test_run(vec4(1, 2, 3, 4) * 2.0, vec4(2, 4, 6, 8));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_run(vec2(1, 2) / 2.0, vec2(0.5, 1.0)); fennec_test_run(vec2(1, 2) / 2.0, vec2(0.5, 1.0));
fennec_test_run(vec3(1, 2, 4) / 2.0, vec3(0.5, 1.0, 2.0)); fennec_test_run(vec3(1, 2, 4) / 2.0, vec3(0.5, 1.0, 2.0));
fennec_test_run(vec4(1, 2, 4, 8) / 2.0, vec4(0.5, 1.0, 2.0, 4.0)); fennec_test_run(vec4(1, 2, 4, 8) / 2.0, vec4(0.5, 1.0, 2.0, 4.0));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_run(ivec2(1, 2) % 2, ivec2(1, 0)); fennec_test_run(ivec2(1, 2) % 2, ivec2(1, 0));
fennec_test_run(ivec3(1, 2, 3) % 2, ivec3(1, 0, 1)); fennec_test_run(ivec3(1, 2, 3) % 2, ivec3(1, 0, 1));
fennec_test_run(ivec4(1, 2, 3, 4) % 2, ivec4(1, 0, 1, 0)); fennec_test_run(ivec4(1, 2, 3, 4) % 2, ivec4(1, 0, 1, 0));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_section("vector-scalar arithmetic assignment operations"); fennec_test_section("vector-scalar arithmetic assignment operations");
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(([]() -> vec2 { vec2 v{ 1, 2 }; return v += 2.0; }()), vec2(3, 4)); fennec_test_run(([]() -> vec2 { vec2 v{ 1, 2 }; return v += 2.0; }()), vec2(3, 4));
fennec_test_run(([]() -> vec3 { vec3 v{ 1, 2, 3 }; return v += 2.0; }()), vec3(3, 4, 5)); fennec_test_run(([]() -> vec3 { vec3 v{ 1, 2, 3 }; return v += 2.0; }()), vec3(3, 4, 5));
fennec_test_run(([]() -> vec4 { vec4 v{ 1, 2, 3, 4 }; return v += 2.0; }()), vec4(3, 4, 5, 6)); fennec_test_run(([]() -> vec4 { vec4 v{ 1, 2, 3, 4 }; return v += 2.0; }()), vec4(3, 4, 5, 6));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_run(([]() -> vec2 { vec2 v{ 1, 2 }; return v -= 2.0; }()), vec2(-1, 0)); fennec_test_run(([]() -> vec2 { vec2 v{ 1, 2 }; return v -= 2.0; }()), vec2(-1, 0));
fennec_test_run(([]() -> vec3 { vec3 v{ 1, 2, 3 }; return v -= 2.0; }()), vec3(-1, 0, 1)); fennec_test_run(([]() -> vec3 { vec3 v{ 1, 2, 3 }; return v -= 2.0; }()), vec3(-1, 0, 1));
fennec_test_run(([]() -> vec4 { vec4 v{ 1, 2, 3, 4 }; return v -= 2.0; }()), vec4(-1, 0, 1, 2)); fennec_test_run(([]() -> vec4 { vec4 v{ 1, 2, 3, 4 }; return v -= 2.0; }()), vec4(-1, 0, 1, 2));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_run(([]() -> vec2 { vec2 v{ 1, 2 }; return v *= 2.0; }()), vec2(2, 4)); fennec_test_run(([]() -> vec2 { vec2 v{ 1, 2 }; return v *= 2.0; }()), vec2(2, 4));
fennec_test_run(([]() -> vec3 { vec3 v{ 1, 2, 3 }; return v *= 2.0; }()), vec3(2, 4, 6)); fennec_test_run(([]() -> vec3 { vec3 v{ 1, 2, 3 }; return v *= 2.0; }()), vec3(2, 4, 6));
fennec_test_run(([]() -> vec4 { vec4 v{ 1, 2, 3, 4 }; return v *= 2.0; }()), vec4(2, 4, 6, 8)); fennec_test_run(([]() -> vec4 { vec4 v{ 1, 2, 3, 4 }; return v *= 2.0; }()), vec4(2, 4, 6, 8));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_run(([]() -> vec2 { vec2 v{ 1, 2 }; return v /= 2.0; }()), vec2(0.5, 1.0)); fennec_test_run(([]() -> vec2 { vec2 v{ 1, 2 }; return v /= 2.0; }()), vec2(0.5, 1.0));
fennec_test_run(([]() -> vec3 { vec3 v{ 1, 2, 3 }; return v /= 2.0; }()), vec3(0.5, 1.0, 1.5)); fennec_test_run(([]() -> vec3 { vec3 v{ 1, 2, 3 }; return v /= 2.0; }()), vec3(0.5, 1.0, 1.5));
fennec_test_run(([]() -> vec4 { vec4 v{ 1, 2, 3, 4 }; return v /= 2.0; }()), vec4(0.5, 1.0, 1.5, 2.0)); fennec_test_run(([]() -> vec4 { vec4 v{ 1, 2, 3, 4 }; return v /= 2.0; }()), vec4(0.5, 1.0, 1.5, 2.0));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_run(([]() -> ivec2 { ivec2 v{ 1, 2 }; return v %= 2; }()), ivec2(1, 0)); fennec_test_run(([]() -> ivec2 { ivec2 v{ 1, 2 }; return v %= 2; }()), ivec2(1, 0));
fennec_test_run(([]() -> ivec3 { ivec3 v{ 1, 2, 3 }; return v %= 2; }()), ivec3(1, 0, 1)); fennec_test_run(([]() -> ivec3 { ivec3 v{ 1, 2, 3 }; return v %= 2; }()), ivec3(1, 0, 1));
fennec_test_run(([]() -> ivec4 { ivec4 v{ 1, 2, 3, 4 }; return v %= 2; }()), ivec4(1, 0, 1, 0)); fennec_test_run(([]() -> ivec4 { ivec4 v{ 1, 2, 3, 4 }; return v %= 2; }()), ivec4(1, 0, 1, 0));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_section("vector-vector arithmetic operations"); fennec_test_section("vector-vector arithmetic operations");
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(vec2(1, 2) + vec2(1, 2), vec2(2, 4)); fennec_test_run(vec2(1, 2) + vec2(1, 2), vec2(2, 4));
fennec_test_run(vec3(1, 2, 3) + vec3(1, 2, 3), vec3(2, 4, 6)); fennec_test_run(vec3(1, 2, 3) + vec3(1, 2, 3), vec3(2, 4, 6));
fennec_test_run(vec4(1, 2, 3, 4) + vec4(1, 2, 3, 4), vec4(2, 4, 6, 8)); fennec_test_run(vec4(1, 2, 3, 4) + vec4(1, 2, 3, 4), vec4(2, 4, 6, 8));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(vec2(1, 2) - vec2(1, 2), vec2(0, 0)); fennec_test_run(vec2(1, 2) - vec2(1, 2), vec2(0, 0));
fennec_test_run(vec3(1, 2, 3) - vec3(1, 2, 3), vec3(0, 0, 0)); fennec_test_run(vec3(1, 2, 3) - vec3(1, 2, 3), vec3(0, 0, 0));
fennec_test_run(vec4(1, 2, 3, 4) - vec4(1, 2, 3, 4), vec4(0, 0, 0, 0)); fennec_test_run(vec4(1, 2, 3, 4) - vec4(1, 2, 3, 4), vec4(0, 0, 0, 0));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(vec2(1, 2) * vec2(1, 2), vec2(1, 4)); fennec_test_run(vec2(1, 2) * vec2(1, 2), vec2(1, 4));
fennec_test_run(vec3(1, 2, 3) * vec3(1, 2, 3), vec3(1, 4, 9)); fennec_test_run(vec3(1, 2, 3) * vec3(1, 2, 3), vec3(1, 4, 9));
fennec_test_run(vec4(1, 2, 3, 4) * vec4(1, 2, 3, 4), vec4(1, 4, 9, 16)); fennec_test_run(vec4(1, 2, 3, 4) * vec4(1, 2, 3, 4), vec4(1, 4, 9, 16));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(vec2(1, 2) / vec2(1, 2), vec2(1, 1)); fennec_test_run(vec2(1, 2) / vec2(1, 2), vec2(1, 1));
fennec_test_run(vec3(1, 2, 4) / vec3(1, 2, 4), vec3(1, 1, 1)); fennec_test_run(vec3(1, 2, 4) / vec3(1, 2, 4), vec3(1, 1, 1));
fennec_test_run(vec4(1, 2, 4, 8) / vec4(1, 2, 4, 8), vec4(1, 1, 1, 1)); fennec_test_run(vec4(1, 2, 4, 8) / vec4(1, 2, 4, 8), vec4(1, 1, 1, 1));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(ivec2(1, 2) % ivec2(1, 2), ivec2(0, 0)); fennec_test_run(ivec2(1, 2) % ivec2(1, 2), ivec2(0, 0));
fennec_test_run(ivec3(1, 2, 4) % ivec3(1, 2, 4), ivec3(0, 0, 0)); fennec_test_run(ivec3(1, 2, 4) % ivec3(1, 2, 4), ivec3(0, 0, 0));
fennec_test_run(ivec4(1, 2, 4, 8) % ivec4(1, 2, 4, 8), ivec4(0, 0, 0, 0)); fennec_test_run(ivec4(1, 2, 4, 8) % ivec4(1, 2, 4, 8), ivec4(0, 0, 0, 0));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_section("vector-vector arithmetic assignment operations"); fennec_test_section("vector-vector arithmetic assignment operations");
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(([]() -> vec2 { vec2 v(1, 2); return v += vec2(1, 2); }()), vec2(2, 4)); fennec_test_run(([]() -> vec2 { vec2 v(1, 2); return v += vec2(1, 2); }()), vec2(2, 4));
fennec_test_run(([]() -> vec3 { vec3 v(1, 2, 3); return v += vec3(1, 2, 3); }()), vec3(2, 4, 6)); fennec_test_run(([]() -> vec3 { vec3 v(1, 2, 3); return v += vec3(1, 2, 3); }()), vec3(2, 4, 6));
fennec_test_run(([]() -> vec4 { vec4 v(1, 2, 3, 4); return v += vec4(1, 2, 3, 4); }()), vec4(2, 4, 6, 8)); fennec_test_run(([]() -> vec4 { vec4 v(1, 2, 3, 4); return v += vec4(1, 2, 3, 4); }()), vec4(2, 4, 6, 8));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(([]() -> vec2 { vec2 v(1, 2); return v -= vec2(1, 2); }()), vec2(0, 0)); fennec_test_run(([]() -> vec2 { vec2 v(1, 2); return v -= vec2(1, 2); }()), vec2(0, 0));
fennec_test_run(([]() -> vec3 { vec3 v(1, 2, 3); return v -= vec3(1, 2, 3); }()), vec3(0, 0, 0)); fennec_test_run(([]() -> vec3 { vec3 v(1, 2, 3); return v -= vec3(1, 2, 3); }()), vec3(0, 0, 0));
fennec_test_run(([]() -> vec4 { vec4 v(1, 2, 3, 4); return v -= vec4(1, 2, 3, 4); }()), vec4(0, 0, 0, 0)); fennec_test_run(([]() -> vec4 { vec4 v(1, 2, 3, 4); return v -= vec4(1, 2, 3, 4); }()), vec4(0, 0, 0, 0));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(([]() -> vec2 { vec2 v(1, 2); return v *= vec2(1, 2); }()), vec2(1, 4)); fennec_test_run(([]() -> vec2 { vec2 v(1, 2); return v *= vec2(1, 2); }()), vec2(1, 4));
fennec_test_run(([]() -> vec3 { vec3 v(1, 2, 3); return v *= vec3(1, 2, 3); }()), vec3(1, 4, 9)); fennec_test_run(([]() -> vec3 { vec3 v(1, 2, 3); return v *= vec3(1, 2, 3); }()), vec3(1, 4, 9));
fennec_test_run(([]() -> vec4 { vec4 v(1, 2, 3, 4); return v *= vec4(1, 2, 3, 4); }()), vec4(1, 4, 9, 16)); fennec_test_run(([]() -> vec4 { vec4 v(1, 2, 3, 4); return v *= vec4(1, 2, 3, 4); }()), vec4(1, 4, 9, 16));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(([]() -> vec2 { vec2 v(1, 2); return v /= vec2(1, 2); }()), vec2(1, 1)); fennec_test_run(([]() -> vec2 { vec2 v(1, 2); return v /= vec2(1, 2); }()), vec2(1, 1));
fennec_test_run(([]() -> vec3 { vec3 v(1, 2, 4); return v /= vec3(1, 2, 4); }()), vec3(1, 1, 1)); fennec_test_run(([]() -> vec3 { vec3 v(1, 2, 4); return v /= vec3(1, 2, 4); }()), vec3(1, 1, 1));
fennec_test_run(([]() -> vec4 { vec4 v(1, 2, 4, 8); return v /= vec4(1, 2, 4, 8); }()), vec4(1, 1, 1, 1)); fennec_test_run(([]() -> vec4 { vec4 v(1, 2, 4, 8); return v /= vec4(1, 2, 4, 8); }()), vec4(1, 1, 1, 1));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(([]() -> ivec2 { ivec2 v(1, 2); return v %= ivec2(1, 2); }()), ivec2(0, 0)); fennec_test_run(([]() -> ivec2 { ivec2 v(1, 2); return v %= ivec2(1, 2); }()), ivec2(0, 0));
fennec_test_run(([]() -> ivec3 { ivec3 v(1, 2, 4); return v %= ivec3(1, 2, 4); }()), ivec3(0, 0, 0)); fennec_test_run(([]() -> ivec3 { ivec3 v(1, 2, 4); return v %= ivec3(1, 2, 4); }()), ivec3(0, 0, 0));
fennec_test_run(([]() -> ivec4 { ivec4 v(1, 2, 4, 8); return v %= ivec4(1, 2, 4, 8); }()), ivec4(0, 0, 0, 0)); fennec_test_run(([]() -> ivec4 { ivec4 v(1, 2, 4, 8); return v %= ivec4(1, 2, 4, 8); }()), ivec4(0, 0, 0, 0));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_section("boolean operations"); fennec_test_section("boolean operations");
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(not bvec2(false, false), bvec2(true, true)); fennec_test_run(not bvec2(false, false), bvec2(true, true));
fennec_test_run(not bvec3(false, false, true), bvec3(true, true, false)); fennec_test_run(not bvec3(false, false, true), bvec3(true, true, false));
fennec_test_run(not bvec4(false, false, true, true), bvec4(true, true, false, false)); fennec_test_run(not bvec4(false, false, true, true), bvec4(true, true, false, false));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(bvec2(false, false) && true, bvec2(false, false)); fennec_test_run(bvec2(false, false) && true, bvec2(false, false));
fennec_test_run(bvec3(false, false, true) && true, bvec3(false, false, true)); fennec_test_run(bvec3(false, false, true) && true, bvec3(false, false, true));
fennec_test_run(bvec4(false, false, true, true) && true, bvec4(false, false, true, true)); fennec_test_run(bvec4(false, false, true, true) && true, bvec4(false, false, true, true));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(bvec2(false, false) && bvec2(false, true), bvec2(false, false)); fennec_test_run(bvec2(false, false) && bvec2(false, true), bvec2(false, false));
fennec_test_run(bvec3(false, false, true) && bvec3(false, true, false), bvec3(false, false, false)); fennec_test_run(bvec3(false, false, true) && bvec3(false, true, false), bvec3(false, false, false));
fennec_test_run(bvec4(false, false, true, true) && bvec4(false, true, false, true), bvec4(false, false, false, true)); fennec_test_run(bvec4(false, false, true, true) && bvec4(false, true, false, true), bvec4(false, false, false, true));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_run(bvec2(false, false) || true, bvec2(true, true)); fennec_test_run(bvec2(false, false) || true, bvec2(true, true));
fennec_test_run(bvec3(false, false, true) || true, bvec3(true, true, true)); fennec_test_run(bvec3(false, false, true) || true, bvec3(true, true, true));
fennec_test_run(bvec4(false, false, true, true) || true, bvec4(true, true, true, true)); fennec_test_run(bvec4(false, false, true, true) || true, bvec4(true, true, true, true));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(bvec2(false, false) || bvec2(false, true), bvec2(false, true)); fennec_test_run(bvec2(false, false) || bvec2(false, true), bvec2(false, true));
fennec_test_run(bvec3(false, false, true) || bvec3(false, true, false), bvec3(false, true, true)); fennec_test_run(bvec3(false, false, true) || bvec3(false, true, false), bvec3(false, true, true));
fennec_test_run(bvec4(false, false, true, true) || bvec4(false, true, false, true), bvec4(false, true, true, true)); fennec_test_run(bvec4(false, false, true, true) || bvec4(false, true, false, true), bvec4(false, true, true, true));
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_section("bitwise operations"); fennec_test_section("bitwise operations");
fennec_test_spacer(1); // bitwise and ============================================================================== fennec_test_spacer(1); // bitwise and ==============================================================================
fennec_test_run(0b0101 & ivec2(0b0001, 0b0010), ivec2(0b0001, 0b0000)); fennec_test_run(0b0101 & ivec2(0b0001, 0b0010), ivec2(0b0001, 0b0000));
fennec_test_run(0b0101 & ivec3(0b0001, 0b0010, 0b0011), ivec3(0b0001, 0b0000, 0b0001)); fennec_test_run(0b0101 & ivec3(0b0001, 0b0010, 0b0011), ivec3(0b0001, 0b0000, 0b0001));
fennec_test_run(0b0101 & ivec4(0b0001, 0b0010, 0b0011, 0b0100), ivec4(0b0001, 0b0000, 0b0001, 0b0100)); fennec_test_run(0b0101 & ivec4(0b0001, 0b0010, 0b0011, 0b0100), ivec4(0b0001, 0b0000, 0b0001, 0b0100));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(ivec2(0b0001, 0b0010) & 0b0101, ivec2(0b0001, 0b0000)); fennec_test_run(ivec2(0b0001, 0b0010) & 0b0101, ivec2(0b0001, 0b0000));
fennec_test_run(ivec3(0b0001, 0b0010, 0b0011) & 0b0101, ivec3(0b0001, 0b0000, 0b0001)); fennec_test_run(ivec3(0b0001, 0b0010, 0b0011) & 0b0101, ivec3(0b0001, 0b0000, 0b0001));
fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) & 0b0101, ivec4(0b0001, 0b0000, 0b0001, 0b0100)); fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) & 0b0101, ivec4(0b0001, 0b0000, 0b0001, 0b0100));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010); return v &= 0b0101; }()), ivec2(0b0001, 0b0000)); fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010); return v &= 0b0101; }()), ivec2(0b0001, 0b0000));
fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011); return v &= 0b0101; }()), ivec3(0b0001, 0b0000, 0b0001)); fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011); return v &= 0b0101; }()), ivec3(0b0001, 0b0000, 0b0001));
fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v &= 0b0101; }()), ivec4(0b0001, 0b0000, 0b0001, 0b0100)); fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v &= 0b0101; }()), ivec4(0b0001, 0b0000, 0b0001, 0b0100));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(ivec2(0b0001, 0b0010) & ivec2(0b1000, 0b0100), ivec2(0b0000)); fennec_test_run(ivec2(0b0001, 0b0010) & ivec2(0b1000, 0b0100), ivec2(0b0000));
fennec_test_run(ivec3(0b0001, 0b0010, 0b0011) & ivec3(0b1000, 0b0100, 0b1100), ivec3(0b0000)); fennec_test_run(ivec3(0b0001, 0b0010, 0b0011) & ivec3(0b1000, 0b0100, 0b1100), ivec3(0b0000));
fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) & ivec4(0b1000, 0b0100, 0b1100, 0b0010), ivec4(0b0000)); fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) & ivec4(0b1000, 0b0100, 0b1100, 0b0010), ivec4(0b0000));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010); return v &= ivec2(0b1000, 0b0100); }()), ivec2(0b0000)); fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010); return v &= ivec2(0b1000, 0b0100); }()), ivec2(0b0000));
fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011); return v &= ivec3(0b1000, 0b0100, 0b1100); }()), ivec3(0b0000)); fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011); return v &= ivec3(0b1000, 0b0100, 0b1100); }()), ivec3(0b0000));
fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v &= ivec4(0b1000, 0b0100, 0b1100, 0b0010); }()), ivec4(0b0000)); fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v &= ivec4(0b1000, 0b0100, 0b1100, 0b0010); }()), ivec4(0b0000));
fennec_test_spacer(2); // bitwise or =============================================================================== fennec_test_spacer(2); // bitwise or ===============================================================================
fennec_test_run(0b0101 | ivec2(0b0001, 0b0010), ivec2(0b0101, 0b0111)); fennec_test_run(0b0101 | ivec2(0b0001, 0b0010), ivec2(0b0101, 0b0111));
fennec_test_run(0b0101 | ivec3(0b0001, 0b0010, 0b0011), ivec3(0b0101, 0b0111, 0b0111)); fennec_test_run(0b0101 | ivec3(0b0001, 0b0010, 0b0011), ivec3(0b0101, 0b0111, 0b0111));
fennec_test_run(0b0101 | ivec4(0b0001, 0b0010, 0b0011, 0b0100), ivec4(0b0101, 0b0111, 0b0111, 0b0101)); fennec_test_run(0b0101 | ivec4(0b0001, 0b0010, 0b0011, 0b0100), ivec4(0b0101, 0b0111, 0b0111, 0b0101));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(ivec2(0b0001, 0b0010) | 0b0101, ivec2(0b0101, 0b0111)); fennec_test_run(ivec2(0b0001, 0b0010) | 0b0101, ivec2(0b0101, 0b0111));
fennec_test_run(ivec3(0b0001, 0b0010, 0b0011) | 0b0101, ivec3(0b0101, 0b0111, 0b0111)); fennec_test_run(ivec3(0b0001, 0b0010, 0b0011) | 0b0101, ivec3(0b0101, 0b0111, 0b0111));
fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) | 0b0101, ivec4(0b0101, 0b0111, 0b0111, 0b0101)); fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) | 0b0101, ivec4(0b0101, 0b0111, 0b0111, 0b0101));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010); return v |= 0b0101; }()), ivec2(0b0101, 0b0111)); fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010); return v |= 0b0101; }()), ivec2(0b0101, 0b0111));
fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011); return v |= 0b0101; }()), ivec3(0b0101, 0b0111, 0b0111)); fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011); return v |= 0b0101; }()), ivec3(0b0101, 0b0111, 0b0111));
fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v |= 0b0101; }()), ivec4(0b0101, 0b0111, 0b0111, 0b0101)); fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v |= 0b0101; }()), ivec4(0b0101, 0b0111, 0b0111, 0b0101));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(ivec2(0b0001, 0b0010) | ivec2(0b1000, 0b0100), ivec2(0b1001, 0b0110)); fennec_test_run(ivec2(0b0001, 0b0010) | ivec2(0b1000, 0b0100), ivec2(0b1001, 0b0110));
fennec_test_run(ivec3(0b0001, 0b0010, 0b0011) | ivec3(0b1000, 0b0100, 0b1100), ivec3(0b1001, 0b0110, 0b1111)); fennec_test_run(ivec3(0b0001, 0b0010, 0b0011) | ivec3(0b1000, 0b0100, 0b1100), ivec3(0b1001, 0b0110, 0b1111));
fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) | ivec4(0b1000, 0b0100, 0b1100, 0b0010), ivec4(0b1001, 0b0110, 0b1111, 0b0110)); fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) | ivec4(0b1000, 0b0100, 0b1100, 0b0010), ivec4(0b1001, 0b0110, 0b1111, 0b0110));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010); return v |= ivec2(0b1000, 0b0100); }()), ivec2(0b1001, 0b0110)); fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010); return v |= ivec2(0b1000, 0b0100); }()), ivec2(0b1001, 0b0110));
fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011); return v |= ivec3(0b1000, 0b0100, 0b1100); }()), ivec3(0b1001, 0b0110, 0b1111)); fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011); return v |= ivec3(0b1000, 0b0100, 0b1100); }()), ivec3(0b1001, 0b0110, 0b1111));
fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v |= ivec4(0b1000, 0b0100, 0b1100, 0b0010); }()), ivec4(0b1001, 0b0110, 0b1111, 0b0110)); fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v |= ivec4(0b1000, 0b0100, 0b1100, 0b0010); }()), ivec4(0b1001, 0b0110, 0b1111, 0b0110));
fennec_test_spacer(2); // bitwise xor ============================================================================== fennec_test_spacer(2); // bitwise xor ==============================================================================
fennec_test_run(0b0101 ^ ivec2(0b0001, 0b0010), ivec2(0b0100, 0b0111)); fennec_test_run(0b0101 ^ ivec2(0b0001, 0b0010), ivec2(0b0100, 0b0111));
fennec_test_run(0b0101 ^ ivec3(0b0001, 0b0010, 0b0011), ivec3(0b0100, 0b0111, 0b0110)); fennec_test_run(0b0101 ^ ivec3(0b0001, 0b0010, 0b0011), ivec3(0b0100, 0b0111, 0b0110));
fennec_test_run(0b0101 ^ ivec4(0b0001, 0b0010, 0b0011, 0b0100), ivec4(0b0100, 0b0111, 0b0110, 0b0001)); fennec_test_run(0b0101 ^ ivec4(0b0001, 0b0010, 0b0011, 0b0100), ivec4(0b0100, 0b0111, 0b0110, 0b0001));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(ivec2(0b0001, 0b0010) ^ 0b0101, ivec2(0b0100, 0b0111)); fennec_test_run(ivec2(0b0001, 0b0010) ^ 0b0101, ivec2(0b0100, 0b0111));
fennec_test_run(ivec3(0b0001, 0b0010, 0b0011) ^ 0b0101, ivec3(0b0100, 0b0111, 0b0110)); fennec_test_run(ivec3(0b0001, 0b0010, 0b0011) ^ 0b0101, ivec3(0b0100, 0b0111, 0b0110));
fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) ^ 0b0101, ivec4(0b0100, 0b0111, 0b0110, 0b0001)); fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) ^ 0b0101, ivec4(0b0100, 0b0111, 0b0110, 0b0001));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010); return v ^= 0b0101; }()), ivec2(0b0100, 0b0111)); fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010); return v ^= 0b0101; }()), ivec2(0b0100, 0b0111));
fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011); return v ^= 0b0101; }()), ivec3(0b0100, 0b0111, 0b0110)); fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011); return v ^= 0b0101; }()), ivec3(0b0100, 0b0111, 0b0110));
fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v ^= 0b0101; }()), ivec4(0b0100, 0b0111, 0b0110, 0b0001)); fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v ^= 0b0101; }()), ivec4(0b0100, 0b0111, 0b0110, 0b0001));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(ivec2(0b0001, 0b0010) ^ ivec2(0b1000, 0b0100), ivec2(0b1001, 0b0110)); fennec_test_run(ivec2(0b0001, 0b0010) ^ ivec2(0b1000, 0b0100), ivec2(0b1001, 0b0110));
fennec_test_run(ivec3(0b0001, 0b0010, 0b0011) ^ ivec3(0b1000, 0b0100, 0b1100), ivec3(0b1001, 0b0110, 0b1111)); fennec_test_run(ivec3(0b0001, 0b0010, 0b0011) ^ ivec3(0b1000, 0b0100, 0b1100), ivec3(0b1001, 0b0110, 0b1111));
fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) ^ ivec4(0b1000, 0b0100, 0b1100, 0b0010), ivec4(0b1001, 0b0110, 0b1111, 0b0110)); fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) ^ ivec4(0b1000, 0b0100, 0b1100, 0b0010), ivec4(0b1001, 0b0110, 0b1111, 0b0110));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010); return v ^= ivec2(0b1000, 0b0100); }()), ivec2(0b1001, 0b0110)); fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010); return v ^= ivec2(0b1000, 0b0100); }()), ivec2(0b1001, 0b0110));
fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011); return v ^= ivec3(0b1000, 0b0100, 0b1100); }()), ivec3(0b1001, 0b0110, 0b1111)); fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011); return v ^= ivec3(0b1000, 0b0100, 0b1100); }()), ivec3(0b1001, 0b0110, 0b1111));
fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v ^= ivec4(0b1000, 0b0100, 0b1100, 0b0010); }()), ivec4(0b1001, 0b0110, 0b1111, 0b0110)); fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v ^= ivec4(0b1000, 0b0100, 0b1100, 0b0010); }()), ivec4(0b1001, 0b0110, 0b1111, 0b0110));
fennec_test_spacer(2); // Left Shift =============================================================================== fennec_test_spacer(2); // Left Shift ===============================================================================
fennec_test_run(0x6D40A3C3 << ivec2(4, 8), ivec2(0xD40A3C30, 0x40A3C300)); fennec_test_run(0x6D40A3C3 << ivec2(4, 8), ivec2(0xD40A3C30, 0x40A3C300));
fennec_test_run(0x6D40A3C3 << ivec3(4, 8, 12), ivec3(0xD40A3C30, 0x40A3C300, 0x0A3C3000)); fennec_test_run(0x6D40A3C3 << ivec3(4, 8, 12), ivec3(0xD40A3C30, 0x40A3C300, 0x0A3C3000));
fennec_test_run(0x6D40A3C3 << ivec4(4, 8, 12, 16), ivec4(0xD40A3C30, 0x40A3C300, 0x0A3C3000, 0xA3C30000)); fennec_test_run(0x6D40A3C3 << ivec4(4, 8, 12, 16), ivec4(0xD40A3C30, 0x40A3C300, 0x0A3C3000, 0xA3C30000));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(ivec2(0x1E, 0xF3) << 4, ivec2(0x1E0, 0xF30)); fennec_test_run(ivec2(0x1E, 0xF3) << 4, ivec2(0x1E0, 0xF30));
fennec_test_run(ivec3(0x1E, 0xF3, 0x27) << 4, ivec3(0x1E0, 0xF30, 0x270)); fennec_test_run(ivec3(0x1E, 0xF3, 0x27) << 4, ivec3(0x1E0, 0xF30, 0x270));
fennec_test_run(ivec4(0x1E, 0xF3, 0x27, 0x7C) << 4, ivec4(0x1E0, 0xF30, 0x270, 0x7C0)); fennec_test_run(ivec4(0x1E, 0xF3, 0x27, 0x7C) << 4, ivec4(0x1E0, 0xF30, 0x270, 0x7C0));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(([]() -> ivec2 { ivec2 v(0x1E, 0xF3); return v <<= 4; }()), ivec2(0x1E0, 0xF30)); fennec_test_run(([]() -> ivec2 { ivec2 v(0x1E, 0xF3); return v <<= 4; }()), ivec2(0x1E0, 0xF30));
fennec_test_run(([]() -> ivec3 { ivec3 v(0x1E, 0xF3, 0x27); return v <<= 4; }()), ivec3(0x1E0, 0xF30, 0x270)); fennec_test_run(([]() -> ivec3 { ivec3 v(0x1E, 0xF3, 0x27); return v <<= 4; }()), ivec3(0x1E0, 0xF30, 0x270));
fennec_test_run(([]() -> ivec4 { ivec4 v(0x1E, 0xF3, 0x27, 0x7C); return v <<= 4; }()), ivec4(0x1E0, 0xF30, 0x270, 0x7C0)); fennec_test_run(([]() -> ivec4 { ivec4 v(0x1E, 0xF3, 0x27, 0x7C); return v <<= 4; }()), ivec4(0x1E0, 0xF30, 0x270, 0x7C0));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(ivec2(0x1E, 0xF3) << ivec2(4, 8), ivec2(0x1E0, 0xF300)); fennec_test_run(ivec2(0x1E, 0xF3) << ivec2(4, 8), ivec2(0x1E0, 0xF300));
fennec_test_run(ivec3(0x1E, 0xF3, 0x27) << ivec3(4, 8, 12), ivec3(0x1E0, 0xF300, 0x27000)); fennec_test_run(ivec3(0x1E, 0xF3, 0x27) << ivec3(4, 8, 12), ivec3(0x1E0, 0xF300, 0x27000));
fennec_test_run(ivec4(0x1E, 0xF3, 0x27, 0x7C) << ivec4(4, 8, 12, 16), ivec4(0x1E0, 0xF300, 0x27000, 0x7C0000)); fennec_test_run(ivec4(0x1E, 0xF3, 0x27, 0x7C) << ivec4(4, 8, 12, 16), ivec4(0x1E0, 0xF300, 0x27000, 0x7C0000));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(([]() -> ivec2 { ivec2 v(0x1E, 0xF3); return v <<= ivec2(4, 8); }()), ivec2(0x1E0, 0xF300)); fennec_test_run(([]() -> ivec2 { ivec2 v(0x1E, 0xF3); return v <<= ivec2(4, 8); }()), ivec2(0x1E0, 0xF300));
fennec_test_run(([]() -> ivec3 { ivec3 v(0x1E, 0xF3, 0x27); return v <<= ivec3(4, 8, 12); }()), ivec3(0x1E0, 0xF300, 0x27000)); fennec_test_run(([]() -> ivec3 { ivec3 v(0x1E, 0xF3, 0x27); return v <<= ivec3(4, 8, 12); }()), ivec3(0x1E0, 0xF300, 0x27000));
fennec_test_run(([]() -> ivec4 { ivec4 v(0x1E, 0xF3, 0x27, 0x7C); return v <<= ivec4(4, 8, 12, 16); }()), ivec4(0x1E0, 0xF300, 0x27000, 0x7C0000)); fennec_test_run(([]() -> ivec4 { ivec4 v(0x1E, 0xF3, 0x27, 0x7C); return v <<= ivec4(4, 8, 12, 16); }()), ivec4(0x1E0, 0xF300, 0x27000, 0x7C0000));
fennec_test_spacer(2); // Right Shift =============================================================================== fennec_test_spacer(2); // Right Shift ===============================================================================
fennec_test_run(0x6D40A3C3 >> ivec2(4, 8), ivec2(0x06D40A3C, 0x006D40A3)); fennec_test_run(0x6D40A3C3 >> ivec2(4, 8), ivec2(0x06D40A3C, 0x006D40A3));
fennec_test_run(0x6D40A3C3 >> ivec3(4, 8, 12), ivec3(0x06D40A3C, 0x006D40A3, 0x0006D40A)); fennec_test_run(0x6D40A3C3 >> ivec3(4, 8, 12), ivec3(0x06D40A3C, 0x006D40A3, 0x0006D40A));
fennec_test_run(0x6D40A3C3 >> ivec4(4, 8, 12, 16), ivec4(0x06D40A3C, 0x006D40A3, 0x0006D40A, 0x00006D40)); fennec_test_run(0x6D40A3C3 >> ivec4(4, 8, 12, 16), ivec4(0x06D40A3C, 0x006D40A3, 0x0006D40A, 0x00006D40));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(ivec2(0x1E, 0xF3) >> 4, ivec2(0x1, 0xF)); fennec_test_run(ivec2(0x1E, 0xF3) >> 4, ivec2(0x1, 0xF));
fennec_test_run(ivec3(0x1E, 0xF3, 0x27) >> 4, ivec3(0x1, 0xF, 0x2)); fennec_test_run(ivec3(0x1E, 0xF3, 0x27) >> 4, ivec3(0x1, 0xF, 0x2));
fennec_test_run(ivec4(0x1E, 0xF3, 0x27, 0x7C) >> 4, ivec4(0x1, 0xF, 0x2, 0x7)); fennec_test_run(ivec4(0x1E, 0xF3, 0x27, 0x7C) >> 4, ivec4(0x1, 0xF, 0x2, 0x7));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(([]() -> ivec2 { ivec2 v(0x1E, 0xF3); return v >>= 4; }()), ivec2(0x1, 0xF)); fennec_test_run(([]() -> ivec2 { ivec2 v(0x1E, 0xF3); return v >>= 4; }()), ivec2(0x1, 0xF));
fennec_test_run(([]() -> ivec3 { ivec3 v(0x1E, 0xF3, 0x27); return v >>= 4; }()), ivec3(0x1, 0xF, 0x2)); fennec_test_run(([]() -> ivec3 { ivec3 v(0x1E, 0xF3, 0x27); return v >>= 4; }()), ivec3(0x1, 0xF, 0x2));
fennec_test_run(([]() -> ivec4 { ivec4 v(0x1E, 0xF3, 0x27, 0x7C); return v >>= 4; }()), ivec4(0x1, 0xF, 0x2, 0x7)); fennec_test_run(([]() -> ivec4 { ivec4 v(0x1E, 0xF3, 0x27, 0x7C); return v >>= 4; }()), ivec4(0x1, 0xF, 0x2, 0x7));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(ivec2(0x2A1E, 0x7BF3) >> ivec2(4, 8), ivec2(0x2A1, 0x7B)); fennec_test_run(ivec2(0x2A1E, 0x7BF3) >> ivec2(4, 8), ivec2(0x2A1, 0x7B));
fennec_test_run(ivec3(0x2A1E, 0x7BF3, 0x3927) >> ivec3(4, 8, 12), ivec3(0x2A1, 0x7B, 0x3)); fennec_test_run(ivec3(0x2A1E, 0x7BF3, 0x3927) >> ivec3(4, 8, 12), ivec3(0x2A1, 0x7B, 0x3));
fennec_test_run(ivec4(0x2A1E, 0x7BF3, 0x3927, 0x237C) >> ivec4(4, 8, 12, 16), ivec4(0x2A1, 0x7B, 0x3, 0x0)); fennec_test_run(ivec4(0x2A1E, 0x7BF3, 0x3927, 0x237C) >> ivec4(4, 8, 12, 16), ivec4(0x2A1, 0x7B, 0x3, 0x0));
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(([]() -> ivec2 { ivec2 v(0x2A1E, 0x7BF3); return v >>= ivec2(4, 8); }()), ivec2(0x2A1, 0x7B)); fennec_test_run(([]() -> ivec2 { ivec2 v(0x2A1E, 0x7BF3); return v >>= ivec2(4, 8); }()), ivec2(0x2A1, 0x7B));
fennec_test_run(([]() -> ivec3 { ivec3 v(0x2A1E, 0x7BF3, 0x3927); return v >>= ivec3(4, 8, 12); }()), ivec3(0x2A1, 0x7B, 0x3)); fennec_test_run(([]() -> ivec3 { ivec3 v(0x2A1E, 0x7BF3, 0x3927); return v >>= ivec3(4, 8, 12); }()), ivec3(0x2A1, 0x7B, 0x3));
fennec_test_run(([]() -> ivec4 { ivec4 v(0x2A1E, 0x7BF3, 0x3927, 0x237C); return v >>= ivec4(4, 8, 12, 16); }()), ivec4(0x2A1, 0x7B, 0x3, 0x0)); fennec_test_run(([]() -> ivec4 { ivec4 v(0x2A1E, 0x7BF3, 0x3927, 0x237C); return v >>= ivec4(4, 8, 12, 16); }()), ivec4(0x2A1, 0x7B, 0x3, 0x0));
} }
}
} }

View File

@@ -22,21 +22,16 @@
#include "../../../test.h" #include "../../../test.h"
#include <fennec/platform/linux/wayland/display.h> #include <fennec/platform/linux/wayland/display.h>
namespace fennec namespace fennec::test
{ {
namespace test using namespace wayland;
{
using namespace wayland; inline void fennec_test_platform_linux_wayland(linux_platform& platform) {
inline void fennec_test_platform_linux_wayland(linux_platform& platform) { wayland_display* display = static_cast<wayland_display*>(platform.get_display());
fennec_test_run(display != nullptr, true);
wayland_display* display = static_cast<wayland_display*>(platform.get_display()); }
fennec_test_run(display != nullptr, true);
}
}
} }

View File

@@ -24,27 +24,22 @@
#include "linux/test_wayland.h" #include "linux/test_wayland.h"
#endif #endif
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_platform_linux() {
{
inline void fennec_test_platform_linux() { linux_platform platform(platform::user::client);
linux_platform platform(platform::user::client);
#ifdef FENNEC_LIB_WAYLAND #ifdef FENNEC_LIB_WAYLAND
fennec_test_section("wayland tests"); fennec_test_section("wayland tests");
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_platform_linux_wayland(platform); fennec_test_platform_linux_wayland(platform);
fennec_test_spacer(3); fennec_test_spacer(3);
#endif #endif
// TODO // TODO
} }
}
} }

View File

@@ -21,40 +21,41 @@
#include "containers/test_array.h" #include "containers/test_array.h"
#include "containers/test_dynarray.h" #include "containers/test_dynarray.h"
#include "containers/test_map.h"
#include "containers/test_optional.h" #include "containers/test_optional.h"
#include "containers/test_set.h" #include "containers/test_set.h"
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_containers()
{ {
fennec_test_subheader("optional tests");
fennec_test_spacer(2);
fennec_test_containers_optional();
fennec_test_spacer(3);
inline void fennec_test_containers() fennec_test_subheader("array tests");
{ fennec_test_spacer(2);
fennec_test_subheader("optional tests"); fennec_test_containers_array();
fennec_test_spacer(2); fennec_test_spacer(3);
fennec_test_containers_optional();
fennec_test_spacer(3);
fennec_test_subheader("array tests"); fennec_test_subheader("dynarray tests");
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_containers_array(); fennec_test_containers_dynarray();
fennec_test_spacer(3); fennec_test_spacer(3);
fennec_test_subheader("dynarray tests"); fennec_test_subheader("set tests");
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_containers_dynarray(); fennec_test_containers_set();
fennec_test_spacer(3); fennec_test_spacer(3);
fennec_test_subheader("set tests"); fennec_test_subheader("map tests");
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_containers_set(); fennec_test_containers_map();
// TODO // TODO
} }
}
} }

View File

@@ -24,27 +24,22 @@
#include "./fproc/test_strings.h" #include "./fproc/test_strings.h"
#include "./fproc/test_io.h" #include "./fproc/test_io.h"
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_fproc() {
{ fennec_test_header("strings");
fennec_test_spacer(2);
fennec_test_fproc_strings();
fennec_test_spacer(3);
inline void fennec_test_fproc() { fennec_test_header("io");
fennec_test_header("strings"); fennec_test_spacer(2);
fennec_test_spacer(2); fennec_test_fproc_io();
fennec_test_fproc_strings(); fennec_test_spacer(3);
fennec_test_spacer(3);
fennec_test_header("io"); // TODO
fennec_test_spacer(2); }
fennec_test_fproc_io();
fennec_test_spacer(3);
// TODO
}
}
} }

View File

@@ -23,27 +23,22 @@
#include "lang/test_conditional_types.h" #include "lang/test_conditional_types.h"
#include "lang/test_hashing.h" #include "lang/test_hashing.h"
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_lang()
{ {
fennec_test_subheader("bit tests");
fennec_test_spacer(2);
fennec_test_lang_bits();
fennec_test_spacer(3);
inline void fennec_test_lang() fennec_test_subheader("hashing tests");
{ fennec_test_spacer(2);
fennec_test_subheader("bit tests"); fennec_test_lang_hashing();
fennec_test_spacer(2);
fennec_test_lang_bits();
fennec_test_spacer(3);
fennec_test_subheader("hashing tests"); // TODO
fennec_test_spacer(2); }
fennec_test_lang_hashing();
// TODO
}
}
} }

View File

@@ -31,63 +31,58 @@
#include "math/test_ext.h" #include "math/test_ext.h"
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_math()
{ {
fennec_test_subheader("scalar tests");
fennec_test_spacer(2);
fennec_test_math_scalar();
fennec_test_spacer(3);
inline void fennec_test_math() fennec_test_subheader("vector tests");
{ fennec_test_spacer(2);
fennec_test_subheader("scalar tests"); fennec_test_math_vector();
fennec_test_spacer(2); fennec_test_spacer(3);
fennec_test_math_scalar();
fennec_test_spacer(3);
fennec_test_subheader("vector tests"); fennec_test_subheader("matrix tests");
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_math_vector(); fennec_test_math_matrix();
fennec_test_spacer(3); fennec_test_spacer(3);
fennec_test_subheader("matrix tests"); fennec_test_subheader("common tests");
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_math_matrix(); fennec_test_math_common();
fennec_test_spacer(3); fennec_test_spacer(3);
fennec_test_subheader("common tests"); fennec_test_subheader("exponential tests");
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_math_common(); fennec_test_math_exponential();
fennec_test_spacer(3); fennec_test_spacer(3);
fennec_test_subheader("exponential tests"); fennec_test_subheader("geometric tests");
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_math_exponential(); fennec_test_math_geometric();
fennec_test_spacer(3); fennec_test_spacer(3);
fennec_test_subheader("geometric tests"); fennec_test_subheader("relational tests");
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_math_geometric(); fennec_test_math_relational();
fennec_test_spacer(3); fennec_test_spacer(3);
fennec_test_subheader("relational tests"); fennec_test_subheader("trigonometric tests");
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_math_relational(); fennec_test_math_trigonometric();
fennec_test_spacer(3); fennec_test_spacer(3);
fennec_test_subheader("trigonometric tests"); fennec_test_header("math extension tests");
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_math_trigonometric(); fennec_test_math_ext();
fennec_test_spacer(3); fennec_test_spacer(3);
fennec_test_header("math extension tests"); // TODO
fennec_test_spacer(2); }
fennec_test_math_ext();
fennec_test_spacer(3);
// TODO
}
}
} }

View File

@@ -24,22 +24,17 @@
#include "./platform/test_linux.h" #include "./platform/test_linux.h"
#endif #endif
namespace fennec namespace fennec::test
{ {
namespace test inline void fennec_test_platform() {
{
inline void fennec_test_platform() {
#if FENNEC_PLATFORM_LINUX #if FENNEC_PLATFORM_LINUX
fennec_test_subheader("linux"); fennec_test_subheader("linux");
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_platform_linux(); fennec_test_platform_linux();
fennec_test_spacer(3); fennec_test_spacer(3);
#endif #endif
} }
}
} }