stage changes

This commit is contained in:
L-Nafaryus 2024-03-14 15:57:16 +05:00
parent 38d628d4ef
commit 39b2063889
Signed by: L-Nafaryus
GPG Key ID: 582F8B0866B294A1
27 changed files with 3393 additions and 2917 deletions

66
.clang-format Normal file
View File

@ -0,0 +1,66 @@
# Generated from CLion C/C++ Code Style settings
BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: None
AlignOperands: Align
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Always
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterReturnType: None
AlwaysBreakTemplateDeclarations: Yes
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: true
BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
ColumnLimit: 0
CompactNamespaces: false
ContinuationIndentWidth: 8
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 4
KeepEmptyLinesAtTheStartOfBlocks: true
MaxEmptyLinesToKeep: 2
NamespaceIndentation: All
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PointerAlignment: Right
ReflowComments: false
SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 0
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 4
UseTab: Never

24
.gitignore vendored
View File

@ -1,13 +1,13 @@
# Xmake cache # Xmake cache
.xmake/ .xmake/
build/ build/
# MacOS Cache # MacOS Cache
.DS_Store/ .DS_Store/
# CMake # CMake
CMakeLists.txt CMakeLists.txt
cmake-build-*/ cmake-build-*/
# Idea # Idea
.idea/ .idea/

15
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,15 @@
{
"configurations": [
{
"name": "windows-gcc",
"compileCommands": ".vscode/compile_commands.json",
"intelliSenseMode": "windows-gcc-x64",
"compilerPath": "C:/Users/Administrator/scoop/apps/msys2/current/mingw64/bin/gcc.exe",
"includePath": [
"${workspaceFolder}/source"
],
"cppStandard": "gnu++20"
}
],
"version": 4
}

26
.vscode/compile_commands.json vendored Normal file
View File

@ -0,0 +1,26 @@
[
{
"directory": "c:\\Users\\Administrator\\Projects\\hpr",
"arguments": ["C:\\Users\\Administrator\\scoop\\apps\\msys2\\current\\mingw64\\bin\\x86_64-w64-mingw32-g++.exe", "-c", "-m64", "-O3", "-std=c++20", "-Isource", "-IC:\\Users\\Administrator\\AppData\\Local\\.xmake\\packages\\i\\imgui\\v1.90-docking\\600835732f214b96b5dbfaccf42f7a60\\include", "-IC:\\Users\\Administrator\\AppData\\Local\\.xmake\\packages\\i\\imgui\\v1.90-docking\\600835732f214b96b5dbfaccf42f7a60\\include\\imgui", "-IC:\\Users\\Administrator\\AppData\\Local\\.xmake\\packages\\i\\imgui\\v1.90-docking\\600835732f214b96b5dbfaccf42f7a60\\include\\backends", "-IC:\\Users\\Administrator\\AppData\\Local\\.xmake\\packages\\i\\imgui\\v1.90-docking\\600835732f214b96b5dbfaccf42f7a60\\include\\misc\\cpp", "-IC:\\Users\\Administrator\\AppData\\Local\\.xmake\\packages\\i\\implot\\v0.15\\6861f774eb2844d6a543372e119845e3\\include", "-IC:\\Users\\Administrator\\AppData\\Local\\.xmake\\packages\\i\\imgui\\v1.90\\853d785fcf03454094beebf60559d12f\\include", "-IC:\\Users\\Administrator\\AppData\\Local\\.xmake\\packages\\i\\imgui\\v1.90\\853d785fcf03454094beebf60559d12f\\include\\imgui", "-IC:\\Users\\Administrator\\AppData\\Local\\.xmake\\packages\\i\\imgui\\v1.90\\853d785fcf03454094beebf60559d12f\\include\\backends", "-IC:\\Users\\Administrator\\AppData\\Local\\.xmake\\packages\\i\\imgui\\v1.90\\853d785fcf03454094beebf60559d12f\\include\\misc\\cpp", "-IC:\\Users\\Administrator\\AppData\\Local\\.xmake\\packages\\g\\glfw\\3.3.8\\d31abc5641874d8fbdc13f33b5569420\\include", "-IC:\\Users\\Administrator\\scoop\\apps\\msys2\\2023-10-26\\mingw64\\include", "-IC:\\Users\\Administrator\\scoop\\apps\\msys2\\2023-10-26\\mingw64\\include\\opencascade", "-DHPR_SCALAR=float", "-DGLFW_INCLUDE_NONE", "-DNDEBUG", "-o", "build\\.objs\\hpr\\mingw\\x86_64\\release\\source\\hpr\\hpr.cpp.obj", "source\\hpr\\hpr.cpp"],
"file": "source\\hpr\\hpr.cpp"
},
{
"directory": "c:\\Users\\Administrator\\Projects\\hpr",
"arguments": ["C:\\Users\\Administrator\\scoop\\apps\\msys2\\current\\mingw64\\bin\\x86_64-w64-mingw32-g++.exe", "-c", "-m64", "-fvisibility=hidden", "-fvisibility-inlines-hidden", "-O3", "-std=c++20", "-Isource", "-IC:\\Users\\Administrator\\AppData\\Local\\.xmake\\packages\\g\\gtest\\1.12.1\\40112995bdf04048acde0ee5a34578c3\\include", "-DHPR_SCALAR=float", "-DNDEBUG", "-o", "build\\.objs\\tests\\mingw\\x86_64\\release\\source\\hpr\\tests\\main.cpp.obj", "source\\hpr\\tests\\main.cpp"],
"file": "source\\hpr\\tests\\main.cpp"
},
{
"directory": "c:\\Users\\Administrator\\Projects\\hpr",
"arguments": ["C:\\Users\\Administrator\\scoop\\apps\\msys2\\current\\mingw64\\bin\\x86_64-w64-mingw32-g++.exe", "-c", "-m64", "-fvisibility=hidden", "-fvisibility-inlines-hidden", "-O3", "-std=c++20", "-Isource", "-IC:\\Users\\Administrator\\AppData\\Local\\.xmake\\packages\\g\\gtest\\1.12.1\\40112995bdf04048acde0ee5a34578c3\\include", "-DHPR_SCALAR=float", "-DNDEBUG", "-o", "build\\.objs\\tests\\mingw\\x86_64\\release\\source\\hpr\\tests\\test_container.cpp.obj", "source\\hpr\\tests\\test_container.cpp"],
"file": "source\\hpr\\tests\\test_container.cpp"
},
{
"directory": "c:\\Users\\Administrator\\Projects\\hpr",
"arguments": ["C:\\Users\\Administrator\\scoop\\apps\\msys2\\current\\mingw64\\bin\\x86_64-w64-mingw32-g++.exe", "-c", "-m64", "-fvisibility=hidden", "-fvisibility-inlines-hidden", "-O3", "-std=c++20", "-Isource", "-IC:\\Users\\Administrator\\AppData\\Local\\.xmake\\packages\\g\\gtest\\1.12.1\\40112995bdf04048acde0ee5a34578c3\\include", "-DHPR_SCALAR=float", "-DNDEBUG", "-o", "build\\.objs\\tests\\mingw\\x86_64\\release\\source\\hpr\\tests\\test_math.cpp.obj", "source\\hpr\\tests\\test_math.cpp"],
"file": "source\\hpr\\tests\\test_math.cpp"
},
{
"directory": "c:\\Users\\Administrator\\Projects\\hpr",
"arguments": ["C:\\Users\\Administrator\\scoop\\apps\\msys2\\current\\mingw64\\bin\\x86_64-w64-mingw32-g++.exe", "-c", "-m64", "-fvisibility=hidden", "-fvisibility-inlines-hidden", "-O3", "-std=c++20", "-Isource", "-IC:\\Users\\Administrator\\AppData\\Local\\.xmake\\packages\\g\\gtest\\1.12.1\\40112995bdf04048acde0ee5a34578c3\\include", "-DHPR_SCALAR=float", "-DNDEBUG", "-o", "build\\.objs\\tests\\mingw\\x86_64\\release\\source\\hpr\\tests\\test_numeric.cpp.obj", "source\\hpr\\tests\\test_numeric.cpp"],
"file": "source\\hpr\\tests\\test_numeric.cpp"
}]

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <hpr/container/iterator.hpp> #include <hpr/container/iterator.hpp>
#include <hpr/container/sequence.hpp> #include <hpr/container/sequence.hpp>
#include <hpr/container/static_array.hpp> #include <hpr/container/static_array.hpp>
#include <hpr/container/dynamic_array.hpp> #include <hpr/container/dynamic_array.hpp>
#include <hpr/container/tree_node.hpp> #include <hpr/container/tree_node.hpp>

View File

@ -1,307 +1,307 @@
#pragma once #pragma once
#include <hpr/container/sequence.hpp> #include <hpr/container/sequence.hpp>
#include <functional> #include <functional>
#include <limits> #include <limits>
namespace hpr namespace hpr
{ {
// forward declaration // forward declaration
template <typename T> template <typename T>
class DynamicArray; class DynamicArray;
// type traits // type traits
template <typename T> template <typename T>
struct is_sequence<DynamicArray<T>> : public std::true_type struct is_sequence<DynamicArray<T>> : public std::true_type
{}; {};
// aliases // aliases
template <typename T> template <typename T>
using darray = DynamicArray<T>; using darray = DynamicArray<T>;
// class definition // class definition
template <typename T> template <typename T>
class DynamicArray : public Sequence<T> class DynamicArray : public Sequence<T>
{ {
using base = Sequence<T>; using base = Sequence<T>;
public: public:
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using value_type = T; using value_type = T;
using size_type = Size; using size_type = Size;
using pointer = T*; using pointer = T*;
using reference = T&; using reference = T&;
using iterator = Iterator<T>; using iterator = Iterator<T>;
using const_pointer = T const*; using const_pointer = T const*;
using const_reference = T const&; using const_reference = T const&;
using const_iterator = Iterator<const T>; using const_iterator = Iterator<const T>;
public: public:
friend constexpr friend constexpr
void swap(DynamicArray& main, DynamicArray& other) noexcept void swap(DynamicArray& main, DynamicArray& other) noexcept
{ {
using std::swap; using std::swap;
swap(static_cast<base&>(main), static_cast<base&>(other)); swap(static_cast<base&>(main), static_cast<base&>(other));
} }
constexpr constexpr
DynamicArray() noexcept : DynamicArray() noexcept :
base {} base {}
{} {}
constexpr explicit constexpr explicit
DynamicArray(const base& b) noexcept : DynamicArray(const base& b) noexcept :
base {b} base {b}
{} {}
constexpr explicit constexpr explicit
DynamicArray(base&& b) noexcept : DynamicArray(base&& b) noexcept :
base {std::forward<base>(b)} base {std::forward<base>(b)}
{} {}
constexpr constexpr
DynamicArray(const DynamicArray& arr) noexcept : DynamicArray(const DynamicArray& arr) noexcept :
base {static_cast<base>(arr)} base {static_cast<base>(arr)}
{} {}
//! Move constructor //! Move constructor
constexpr constexpr
DynamicArray(DynamicArray&& arr) noexcept : DynamicArray(DynamicArray&& arr) noexcept :
base {std::forward<base>(static_cast<base>(arr))} base {std::forward<base>(static_cast<base>(arr))}
{} {}
template <typename Iter> template <typename Iter>
constexpr constexpr
DynamicArray(Iter start, Iter end) : DynamicArray(Iter start, Iter end) :
base {start, end} base {start, end}
{} {}
constexpr constexpr
DynamicArray(typename base::iterator start, typename base::iterator end) : DynamicArray(typename base::iterator start, typename base::iterator end) :
base {start, end} base {start, end}
{} {}
constexpr constexpr
DynamicArray(typename base::const_iterator start, typename base::const_iterator end) : DynamicArray(typename base::const_iterator start, typename base::const_iterator end) :
base {start, end} base {start, end}
{} {}
constexpr constexpr
DynamicArray(typename base::iterator start, typename base::iterator end, size_type capacity) : DynamicArray(typename base::iterator start, typename base::iterator end, size_type capacity) :
base {start, end, capacity} base {start, end, capacity}
{} {}
constexpr constexpr
DynamicArray(typename base::const_iterator start, typename base::const_iterator end, size_type capacity) : DynamicArray(typename base::const_iterator start, typename base::const_iterator end, size_type capacity) :
base {start, end, capacity} base {start, end, capacity}
{} {}
constexpr constexpr
DynamicArray(std::initializer_list<value_type> list) : DynamicArray(std::initializer_list<value_type> list) :
base {list.begin(), list.end()} base {list.begin(), list.end()}
{} {}
constexpr constexpr
DynamicArray(size_type size, value_type value) noexcept : DynamicArray(size_type size, value_type value) noexcept :
base {size, value} base {size, value}
{} {}
constexpr constexpr
DynamicArray& operator=(base other) noexcept DynamicArray& operator=(base other) noexcept
{ {
swap(*this, other); swap(*this, other);
return *this; return *this;
} }
constexpr constexpr
DynamicArray& operator=(DynamicArray other) noexcept DynamicArray& operator=(DynamicArray other) noexcept
{ {
swap(*this, other); swap(*this, other);
return *this; return *this;
} }
constexpr constexpr
DynamicArray& operator=(DynamicArray&& arr) noexcept DynamicArray& operator=(DynamicArray&& arr) noexcept
{ {
swap(*this, arr); swap(*this, arr);
return *this; return *this;
} }
virtual virtual
~DynamicArray() = default; ~DynamicArray() = default;
// Member functions // Member functions
[[nodiscard]] virtual constexpr [[nodiscard]] virtual constexpr
size_type capacity() const noexcept size_type capacity() const noexcept
{ {
return base::p_capacity; return base::p_capacity;
} }
[[nodiscard]] virtual constexpr [[nodiscard]] virtual constexpr
bool is_empty() const bool is_empty() const
{ {
return base::begin() == base::end(); return base::begin() == base::end();
} }
virtual constexpr virtual constexpr
iterator storage_end() iterator storage_end()
{ {
return iterator(base::p_start + base::p_capacity); return iterator(base::p_start + base::p_capacity);
} }
virtual constexpr virtual constexpr
const_iterator storage_end() const const_iterator storage_end() const
{ {
return const_iterator(base::p_start + base::p_capacity); return const_iterator(base::p_start + base::p_capacity);
} }
virtual constexpr virtual constexpr
void resize(size_type newCapacity) void resize(size_type newCapacity)
{ {
if (newCapacity == base::p_capacity) if (newCapacity == base::p_capacity)
return; return;
if (std::numeric_limits<size_type>::max() - base::size() < newCapacity) if (std::numeric_limits<size_type>::max() - base::size() < newCapacity)
throw hpr::LengthError("Invalid capacity value passed"); throw hpr::LengthError("Invalid capacity value passed");
if (newCapacity > base::p_capacity) if (newCapacity > base::p_capacity)
{ {
DynamicArray tmp {base::begin(), base::end(), newCapacity}; DynamicArray tmp {base::begin(), base::end(), newCapacity};
swap(*this, tmp); swap(*this, tmp);
} }
else else
{ {
if (newCapacity >= base::p_size) if (newCapacity >= base::p_size)
{ {
DynamicArray tmp {base::begin(), base::end()}; DynamicArray tmp {base::begin(), base::end()};
swap(*this, tmp); swap(*this, tmp);
} }
else else
{ {
DynamicArray tmp {base::begin(), base::begin() + newCapacity}; DynamicArray tmp {base::begin(), base::begin() + newCapacity};
swap(*this, tmp); swap(*this, tmp);
} }
} }
} }
virtual constexpr virtual constexpr
void push(const value_type& val) void push(const value_type& val)
{ {
if (base::end() == storage_end()) if (base::end() == storage_end())
resize(base::p_capacity * 2); resize(base::p_capacity * 2);
*base::end() = val; *base::end() = val;
++base::p_size; ++base::p_size;
} }
virtual constexpr virtual constexpr
void push(value_type&& val) void push(value_type&& val)
{ {
if (base::end() == storage_end()) if (base::end() == storage_end())
resize(base::p_capacity * 2); resize(base::p_capacity * 2);
*base::end() = std::move(val); *base::end() = std::move(val);
++base::p_size; ++base::p_size;
} }
virtual constexpr virtual constexpr
void push(const DynamicArray<T>& arr) void push(const DynamicArray<T>& arr)
{ {
for (const value_type& el : arr) for (const value_type& el : arr)
push(el); push(el);
} }
virtual constexpr virtual constexpr
value_type pop() value_type pop()
{ {
if (is_empty()) if (is_empty())
throw hpr::LengthError("Cannot pop element from empty array"); throw hpr::LengthError("Cannot pop element from empty array");
value_type val = base::back(); value_type val = base::back();
std::destroy_at(base::p_start + base::p_size); std::destroy_at(base::p_start + base::p_size);
--base::p_size; --base::p_size;
return val; return val;
} }
virtual constexpr virtual constexpr
void insert(size_type position, const value_type& val) void insert(size_type position, const value_type& val)
{ {
if (base::end() == storage_end()) if (base::end() == storage_end())
resize(base::p_capacity * 2); resize(base::p_capacity * 2);
for (size_type n = base::p_size; n > position; --n) for (size_type n = base::p_size; n > position; --n)
*(base::p_start + n) = std::move(*(base::p_start + n - 1)); *(base::p_start + n) = std::move(*(base::p_start + n - 1));
*(base::p_start + position) = val; *(base::p_start + position) = val;
++base::p_size; ++base::p_size;
} }
virtual constexpr virtual constexpr
void insert(size_type position, value_type&& val) void insert(size_type position, value_type&& val)
{ {
if (base::end() == storage_end()) if (base::end() == storage_end())
resize(base::p_capacity * 2); resize(base::p_capacity * 2);
for (size_type n = base::p_size; n > position; --n) for (size_type n = base::p_size; n > position; --n)
*(base::p_start + n) = std::move(*(base::p_start + n - 1)); *(base::p_start + n) = std::move(*(base::p_start + n - 1));
*(base::p_start + position) = std::move(val); *(base::p_start + position) = std::move(val);
++base::p_size; ++base::p_size;
} }
virtual constexpr virtual constexpr
void remove(size_type position) void remove(size_type position)
{ {
for (size_type n = position; n < base::p_size - 1; ++n) for (size_type n = position; n < base::p_size - 1; ++n)
*(base::p_start + n) = std::move(*(base::p_start + n + 1)); *(base::p_start + n) = std::move(*(base::p_start + n + 1));
std::destroy_at(base::p_start + base::p_size); std::destroy_at(base::p_start + base::p_size);
--base::p_size; --base::p_size;
} }
virtual constexpr virtual constexpr
void remove(iterator position) void remove(iterator position)
{ {
if (position + 1 != base::end()) if (position + 1 != base::end())
std::copy(position + 1, base::end(), position); std::copy(position + 1, base::end(), position);
std::destroy_at(base::p_start + base::p_size); std::destroy_at(base::p_start + base::p_size);
--base::p_size; --base::p_size;
} }
virtual constexpr virtual constexpr
void remove(const std::function<bool(value_type)>& condition) void remove(const std::function<bool(value_type)>& condition)
{ {
size_type newSize = base::p_size; size_type newSize = base::p_size;
for (size_type offset = 0; offset < newSize; ++offset) for (size_type offset = 0; offset < newSize; ++offset)
{ {
if (condition(*(base::p_start + offset))) if (condition(*(base::p_start + offset)))
{ {
for (size_type n = offset; n < newSize; ++n) for (size_type n = offset; n < newSize; ++n)
*(base::p_start + n) = std::move(*(base::p_start + n + 1)); *(base::p_start + n) = std::move(*(base::p_start + n + 1));
--newSize; --newSize;
--offset; --offset;
} }
} }
base::p_size = newSize; base::p_size = newSize;
} }
virtual constexpr virtual constexpr
void clear() void clear()
{ {
delete[] base::p_start; delete[] base::p_start;
base::p_size = 0; base::p_size = 0;
base::p_capacity = 1; base::p_capacity = 1;
base::p_start = new value_type[base::p_capacity]; base::p_start = new value_type[base::p_capacity];
} }
DynamicArray slice(iterator start, iterator end) DynamicArray slice(iterator start, iterator end)
{ {
return DynamicArray {start, end}; return DynamicArray {start, end};
} }
}; };
} // end namespace hpr } // end namespace hpr

View File

@ -1,98 +1,98 @@
#pragma once #pragma once
#include <iterator> #include <iterator>
namespace hpr namespace hpr
{ {
template <typename Type, typename Category = std::forward_iterator_tag> template <typename Type, typename Category = std::forward_iterator_tag>
class Iterator class Iterator
{ {
public: public:
using iterator_category = Category; using iterator_category = Category;
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using value_type = Type; using value_type = Type;
using pointer = Type*; using pointer = Type*;
using reference = Type&; using reference = Type&;
using iterator = Iterator; using iterator = Iterator;
using const_pointer = Type const*; using const_pointer = Type const*;
using const_reference = Type const&; using const_reference = Type const&;
using const_iterator = Iterator const; using const_iterator = Iterator const;
protected: protected:
pointer p_ptr; pointer p_ptr;
public: public:
Iterator() : Iterator() :
p_ptr {nullptr} p_ptr {nullptr}
{} {}
Iterator(pointer ptr) : Iterator(pointer ptr) :
p_ptr {ptr} p_ptr {ptr}
{} {}
reference operator*() reference operator*()
{ {
return *p_ptr; return *p_ptr;
} }
const_reference operator*() const const_reference operator*() const
{ {
return *p_ptr; return *p_ptr;
} }
pointer operator->() pointer operator->()
{ {
return p_ptr; return p_ptr;
} }
const_pointer operator->() const const_pointer operator->() const
{ {
return p_ptr; return p_ptr;
} }
iterator& operator++() iterator& operator++()
{ {
p_ptr++; p_ptr++;
return *this; return *this;
} }
const_iterator& operator++() const const_iterator& operator++() const
{ {
p_ptr++; p_ptr++;
return *this; return *this;
} }
iterator operator++(int) iterator operator++(int)
{ {
iterator temp {*this}; iterator temp {*this};
++(*this); ++(*this);
return temp; return temp;
} }
iterator operator+(int value) iterator operator+(int value)
{ {
iterator temp {*this}; iterator temp {*this};
temp.p_ptr += value; temp.p_ptr += value;
return temp; return temp;
} }
friend friend
bool operator==(const iterator& lhs, const iterator& rhs) bool operator==(const iterator& lhs, const iterator& rhs)
{ {
return lhs.p_ptr == rhs.p_ptr; return lhs.p_ptr == rhs.p_ptr;
} }
friend friend
bool operator!=(const iterator& lhs, const iterator& rhs) bool operator!=(const iterator& lhs, const iterator& rhs)
{ {
return lhs.p_ptr != rhs.p_ptr; return lhs.p_ptr != rhs.p_ptr;
} }
}; };
} // end namespace hpr } // end namespace hpr

View File

@ -1,319 +1,319 @@
#pragma once #pragma once
#include <hpr/container/iterator.hpp> #include <hpr/container/iterator.hpp>
#include <hpr/exception.hpp> #include <hpr/exception.hpp>
#include <hpr/numeric.hpp> #include <hpr/numeric.hpp>
namespace hpr namespace hpr
{ {
// forward declaration // forward declaration
template <typename T> template <typename T>
class Sequence; class Sequence;
// type traits // type traits
template <typename T> template <typename T>
struct is_sequence : public std::false_type struct is_sequence : public std::false_type
{}; {};
template <typename T> template <typename T>
struct is_sequence<Sequence<T>> : public std::true_type struct is_sequence<Sequence<T>> : public std::true_type
{}; {};
// concepts // concepts
template <typename Type> template <typename Type>
concept IsSequence = is_sequence<Type>::value; concept IsSequence = is_sequence<Type>::value;
// class definition // class definition
template <typename T> template <typename T>
class Sequence class Sequence
{ {
public: public:
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using value_type = T; using value_type = T;
using size_type = Size; using size_type = Size;
using pointer = T*; using pointer = T*;
using reference = T&; using reference = T&;
using iterator = Iterator<T>; using iterator = Iterator<T>;
using const_pointer = T const*; using const_pointer = T const*;
using const_reference = T const&; using const_reference = T const&;
using const_iterator = Iterator<const T>; using const_iterator = Iterator<const T>;
protected: protected:
size_type p_size; size_type p_size;
size_type p_capacity; size_type p_capacity;
pointer p_start; pointer p_start;
protected: protected:
constexpr constexpr
Sequence(size_type size, size_type capacity, pointer start) : Sequence(size_type size, size_type capacity, pointer start) :
p_size {size}, p_size {size},
p_capacity {capacity}, p_capacity {capacity},
p_start {start} p_start {start}
{} {}
constexpr explicit constexpr explicit
Sequence(size_type size, size_type capacity) : Sequence(size_type size, size_type capacity) :
p_size {size}, p_size {size},
p_capacity {capacity}, p_capacity {capacity},
p_start {p_capacity ? new value_type[p_capacity] : nullptr} p_start {p_capacity ? new value_type[p_capacity] : nullptr}
{} {}
public: public:
friend constexpr friend constexpr
void swap(Sequence& main, Sequence& other) noexcept void swap(Sequence& main, Sequence& other) noexcept
{ {
using std::swap; using std::swap;
swap(main.p_size, other.p_size); swap(main.p_size, other.p_size);
swap(main.p_capacity, other.p_capacity); swap(main.p_capacity, other.p_capacity);
swap(main.p_start, other.p_start); swap(main.p_start, other.p_start);
} }
constexpr constexpr
Sequence() noexcept : Sequence() noexcept :
p_size {0}, p_size {0},
p_capacity {1}, p_capacity {1},
p_start {new value_type[p_capacity]} p_start {new value_type[p_capacity]}
{} {}
constexpr constexpr
Sequence(const Sequence& seq) noexcept : Sequence(const Sequence& seq) noexcept :
p_size {seq.p_size}, p_size {seq.p_size},
p_capacity {seq.p_capacity}, p_capacity {seq.p_capacity},
p_start {p_capacity ? new value_type[seq.p_capacity] : nullptr} p_start {p_capacity ? new value_type[seq.p_capacity] : nullptr}
{ {
std::copy(seq.p_start, seq.p_start + seq.p_size, p_start); std::copy(seq.p_start, seq.p_start + seq.p_size, p_start);
} }
//! Move constructor //! Move constructor
constexpr constexpr
Sequence(Sequence&& seq) noexcept : Sequence(Sequence&& seq) noexcept :
Sequence {} Sequence {}
{ {
swap(*this, seq); swap(*this, seq);
} }
template <typename Iter> template <typename Iter>
constexpr constexpr
Sequence(Iter start, Iter end) : Sequence(Iter start, Iter end) :
p_size {static_cast<size_type>(std::distance(start, end))}, p_size {static_cast<size_type>(std::distance(start, end))},
p_capacity {p_size}, p_capacity {p_size},
p_start {p_capacity ? new value_type[p_capacity] : nullptr} p_start {p_capacity ? new value_type[p_capacity] : nullptr}
{ {
std::copy(start, end, p_start); std::copy(start, end, p_start);
} }
constexpr constexpr
Sequence(iterator start, iterator end) : Sequence(iterator start, iterator end) :
p_size {static_cast<size_type>(std::distance(start, end))}, p_size {static_cast<size_type>(std::distance(start, end))},
p_capacity {p_size}, p_capacity {p_size},
p_start {p_capacity ? new value_type[p_capacity] : nullptr} p_start {p_capacity ? new value_type[p_capacity] : nullptr}
{ {
std::copy(start, end, p_start); std::copy(start, end, p_start);
} }
constexpr constexpr
Sequence(const_iterator start, const_iterator end) : Sequence(const_iterator start, const_iterator end) :
p_size {static_cast<size_type>(std::distance(start, end))}, p_size {static_cast<size_type>(std::distance(start, end))},
p_capacity {p_size}, p_capacity {p_size},
p_start {p_capacity ? new value_type[p_capacity] : nullptr} p_start {p_capacity ? new value_type[p_capacity] : nullptr}
{ {
std::copy(start, end, p_start); std::copy(start, end, p_start);
} }
constexpr constexpr
Sequence(iterator start, iterator end, size_type capacity) : Sequence(iterator start, iterator end, size_type capacity) :
p_size {static_cast<size_type>(std::distance(start, end))}, p_size {static_cast<size_type>(std::distance(start, end))},
p_capacity {capacity}, p_capacity {capacity},
p_start {p_capacity ? new value_type[p_capacity] : nullptr} p_start {p_capacity ? new value_type[p_capacity] : nullptr}
{ {
std::copy(start, end, p_start); std::copy(start, end, p_start);
} }
constexpr constexpr
Sequence(const_iterator start, const_iterator end, size_type capacity) : Sequence(const_iterator start, const_iterator end, size_type capacity) :
p_size {static_cast<size_type>(std::distance(start, end))}, p_size {static_cast<size_type>(std::distance(start, end))},
p_capacity {capacity}, p_capacity {capacity},
p_start {p_capacity ? new value_type[p_capacity] : nullptr} p_start {p_capacity ? new value_type[p_capacity] : nullptr}
{ {
std::copy(start, end, p_start); std::copy(start, end, p_start);
} }
/*constexpr /*constexpr
Sequence(std::initializer_list<value_type> list) : Sequence(std::initializer_list<value_type> list) :
Sequence {list.begin(), list.end()} Sequence {list.begin(), list.end()}
{}*/ {}*/
constexpr constexpr
Sequence(size_type size, value_type value) noexcept: Sequence(size_type size, value_type value) noexcept:
p_size {size}, p_size {size},
p_capacity {size}, p_capacity {size},
p_start {p_capacity ? new value_type[p_capacity] : nullptr} p_start {p_capacity ? new value_type[p_capacity] : nullptr}
{ {
for (auto n = 0; n < size; ++n) for (auto n = 0; n < size; ++n)
*(p_start + n) = value; *(p_start + n) = value;
} }
constexpr constexpr
Sequence& operator=(Sequence other) noexcept Sequence& operator=(Sequence other) noexcept
{ {
swap(*this, other); swap(*this, other);
return *this; return *this;
} }
constexpr constexpr
Sequence& operator=(Sequence&& seq) noexcept Sequence& operator=(Sequence&& seq) noexcept
{ {
swap(*this, seq); swap(*this, seq);
return *this; return *this;
} }
virtual virtual
~Sequence() ~Sequence()
{ {
delete[] p_start; delete[] p_start;
} }
// Member functions // Member functions
virtual constexpr virtual constexpr
iterator begin() iterator begin()
{ {
return iterator(p_start); return iterator(p_start);
} }
[[nodiscard]] virtual constexpr [[nodiscard]] virtual constexpr
const_iterator begin() const const_iterator begin() const
{ {
return const_iterator(p_start); return const_iterator(p_start);
} }
virtual constexpr virtual constexpr
iterator end() iterator end()
{ {
return iterator(p_start + p_size); return iterator(p_start + p_size);
} }
virtual constexpr virtual constexpr
const_iterator end() const const_iterator end() const
{ {
return const_iterator(p_start + p_size); return const_iterator(p_start + p_size);
} }
virtual constexpr virtual constexpr
iterator storage_end() iterator storage_end()
{ {
return iterator(p_start + p_capacity); return iterator(p_start + p_capacity);
} }
virtual constexpr virtual constexpr
const_iterator storage_end() const const_iterator storage_end() const
{ {
return const_iterator(p_start + p_capacity); return const_iterator(p_start + p_capacity);
} }
[[nodiscard]] virtual constexpr [[nodiscard]] virtual constexpr
size_type size() const noexcept size_type size() const noexcept
{ {
return p_size; return p_size;
} }
virtual constexpr virtual constexpr
reference operator[](size_type n) reference operator[](size_type n)
{ {
if (n >= size()) if (n >= size())
throw hpr::OutOfRange(); throw hpr::OutOfRange();
return *(p_start + n); return *(p_start + n);
} }
virtual constexpr virtual constexpr
const_reference operator[](size_type n) const const_reference operator[](size_type n) const
{ {
if (n >= size()) if (n >= size())
throw hpr::OutOfRange(); throw hpr::OutOfRange();
return *(p_start + n); return *(p_start + n);
} }
virtual constexpr virtual constexpr
reference at(size_type n) reference at(size_type n)
{ {
return operator[](n); return operator[](n);
} }
virtual constexpr virtual constexpr
const_reference at(size_type n) const const_reference at(size_type n) const
{ {
return operator[](n); return operator[](n);
} }
virtual constexpr virtual constexpr
reference front() reference front()
{ {
return *begin(); return *begin();
} }
virtual constexpr virtual constexpr
const_reference front() const const_reference front() const
{ {
return *begin(); return *begin();
} }
virtual constexpr virtual constexpr
reference back() reference back()
{ {
return *(p_start + p_size - 1); return *(p_start + p_size - 1);
} }
virtual constexpr virtual constexpr
const_reference back() const const_reference back() const
{ {
return *(p_start + p_size - 1); return *(p_start + p_size - 1);
} }
virtual constexpr virtual constexpr
pointer data() pointer data()
{ {
return p_start; return p_start;
} }
[[nodiscard]] virtual constexpr [[nodiscard]] virtual constexpr
const_pointer data() const const_pointer data() const
{ {
return p_start; return p_start;
} }
// Friend functions // Friend functions
friend friend
bool operator==(const Sequence& lhs, const Sequence& rhs) bool operator==(const Sequence& lhs, const Sequence& rhs)
{ {
for (auto n = 0; n < lhs.size(); ++n) for (auto n = 0; n < lhs.size(); ++n)
if (lhs[n] != rhs[n]) if (lhs[n] != rhs[n])
return false; return false;
return true; return true;
} }
friend friend
Sequence operator+(const Sequence& lhs, const Sequence& rhs) Sequence operator+(const Sequence& lhs, const Sequence& rhs)
{ {
Sequence seq {rhs.size() + lhs.size(), {}}; Sequence seq {rhs.size() + lhs.size(), {}};
for (auto n = 0; n < rhs.size(); ++n) for (auto n = 0; n < rhs.size(); ++n)
{ {
seq[n] = rhs[n]; seq[n] = rhs[n];
seq[n + rhs.size()] = lhs[n]; seq[n + rhs.size()] = lhs[n];
} }
return seq; return seq;
} }
}; };
} // end namespace hpr } // end namespace hpr

View File

@ -1,146 +1,146 @@
#pragma once #pragma once
#include <hpr/container/sequence.hpp> #include <hpr/container/sequence.hpp>
namespace hpr namespace hpr
{ {
// forward declaration // forward declaration
template <typename T, Size S> template <typename T, Size S>
requires (S > 0) requires (S > 0)
class StaticArray; class StaticArray;
// type traits // type traits
template <typename T, Size S> template <typename T, Size S>
struct is_sequence<StaticArray<T, S>> : public std::true_type struct is_sequence<StaticArray<T, S>> : public std::true_type
{}; {};
// aliases // aliases
template <typename T, Size S> template <typename T, Size S>
using sarray = StaticArray<T, S>; using sarray = StaticArray<T, S>;
// class definition // class definition
template <typename T, Size S> template <typename T, Size S>
requires (S > 0) requires (S > 0)
class StaticArray : public Sequence<T> class StaticArray : public Sequence<T>
{ {
using base = Sequence<T>; using base = Sequence<T>;
public: public:
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using value_type = T; using value_type = T;
using size_type = Size; using size_type = Size;
using pointer = T*; using pointer = T*;
using reference = T&; using reference = T&;
using iterator = Iterator<T>; using iterator = Iterator<T>;
using const_pointer = T const*; using const_pointer = T const*;
using const_reference = T const&; using const_reference = T const&;
using const_iterator = Iterator<const T>; using const_iterator = Iterator<const T>;
public: public:
friend constexpr friend constexpr
void swap(StaticArray& main, StaticArray& other) noexcept void swap(StaticArray& main, StaticArray& other) noexcept
{ {
using std::swap; using std::swap;
swap(static_cast<base&>(main), static_cast<base&>(other)); swap(static_cast<base&>(main), static_cast<base&>(other));
} }
//! Default constructor //! Default constructor
constexpr constexpr
StaticArray() noexcept : StaticArray() noexcept :
base {S, S, new value_type[S] {}} base {S, S, new value_type[S] {}}
{} {}
constexpr explicit constexpr explicit
StaticArray(const base& b) noexcept : StaticArray(const base& b) noexcept :
base {b} base {b}
{} {}
//! Copy constructor //! Copy constructor
constexpr constexpr
StaticArray(const StaticArray& arr) noexcept : StaticArray(const StaticArray& arr) noexcept :
base {static_cast<base>(arr)} base {static_cast<base>(arr)}
{} {}
//! Move constructor //! Move constructor
constexpr constexpr
StaticArray(StaticArray&& arr) noexcept : StaticArray(StaticArray&& arr) noexcept :
base {std::forward<base>(static_cast<base>(arr))} base {std::forward<base>(static_cast<base>(arr))}
{} {}
constexpr constexpr
StaticArray(typename base::iterator start, typename base::iterator end) : StaticArray(typename base::iterator start, typename base::iterator end) :
base {start, end} base {start, end}
{} {}
constexpr constexpr
StaticArray(typename base::const_iterator start, typename base::const_iterator end) : StaticArray(typename base::const_iterator start, typename base::const_iterator end) :
base {start, end} base {start, end}
{} {}
constexpr constexpr
StaticArray(typename base::iterator start, typename base::iterator end, size_type capacity) : StaticArray(typename base::iterator start, typename base::iterator end, size_type capacity) :
base {start, end, capacity} base {start, end, capacity}
{} {}
constexpr constexpr
StaticArray(typename base::const_iterator start, typename base::const_iterator end, size_type capacity) : StaticArray(typename base::const_iterator start, typename base::const_iterator end, size_type capacity) :
base {start, end, capacity} base {start, end, capacity}
{} {}
constexpr constexpr
StaticArray(std::initializer_list<value_type> list) : StaticArray(std::initializer_list<value_type> list) :
base {list.begin(), list.end()} base {list.begin(), list.end()}
{} {}
template <std::convertible_to<value_type>... Args> template <std::convertible_to<value_type>... Args>
constexpr explicit constexpr explicit
StaticArray(const value_type& v, const Args& ...args) StaticArray(const value_type& v, const Args& ...args)
requires (1 + sizeof...(args) == S) : requires (1 + sizeof...(args) == S) :
StaticArray {std::initializer_list<value_type>({v, static_cast<value_type>(args)...})} StaticArray {std::initializer_list<value_type>({v, static_cast<value_type>(args)...})}
{} {}
template <std::convertible_to<value_type>... Args> template <std::convertible_to<value_type>... Args>
constexpr explicit constexpr explicit
StaticArray(value_type&& v, Args&& ...args) StaticArray(value_type&& v, Args&& ...args)
requires (1 + sizeof...(args) == S) : requires (1 + sizeof...(args) == S) :
StaticArray {std::initializer_list<value_type>({std::forward<value_type>(v), std::forward<value_type>(static_cast<value_type>(args))...})} StaticArray {std::initializer_list<value_type>({std::forward<value_type>(v), std::forward<value_type>(static_cast<value_type>(args))...})}
{} {}
template <size_type SS, std::convertible_to<value_type>... Args> template <size_type SS, std::convertible_to<value_type>... Args>
constexpr constexpr
StaticArray(const StaticArray<value_type, SS>& subArr, const value_type& v, const Args& ...args) noexcept StaticArray(const StaticArray<value_type, SS>& subArr, const value_type& v, const Args& ...args) noexcept
requires (SS + 1 + sizeof...(args) == S) : requires (SS + 1 + sizeof...(args) == S) :
base {S, S, new value_type[S] {}} base {S, S, new value_type[S] {}}
{ {
std::copy(subArr.begin(), subArr.end(), base::begin()); std::copy(subArr.begin(), subArr.end(), base::begin());
std::initializer_list<value_type> list {v, static_cast<value_type>(args)...}; std::initializer_list<value_type> list {v, static_cast<value_type>(args)...};
std::copy(list.begin(), list.end(), base::begin() + subArr.size()); std::copy(list.begin(), list.end(), base::begin() + subArr.size());
} }
constexpr constexpr
StaticArray& operator=(StaticArray other) StaticArray& operator=(StaticArray other)
{ {
swap(*this, other); swap(*this, other);
return *this; return *this;
} }
constexpr constexpr
StaticArray& operator=(StaticArray&& other) noexcept StaticArray& operator=(StaticArray&& other) noexcept
{ {
swap(*this, other); swap(*this, other);
return *this; return *this;
} }
virtual virtual
~StaticArray() = default; ~StaticArray() = default;
}; };
} // end namespace hpr } // end namespace hpr

View File

@ -1,181 +1,181 @@
#pragma once #pragma once
#include <hpr/container/dynamic_array.hpp> #include <hpr/container/dynamic_array.hpp>
#include <memory> #include <memory>
namespace hpr namespace hpr
{ {
template <typename Type> template <typename Type>
class TreeNode class TreeNode
{ {
public: public:
using value_type = Type; using value_type = Type;
using pointer = Type*; using pointer = Type*;
using reference = Type&; using reference = Type&;
using const_pointer = Type const*; using const_pointer = Type const*;
using const_reference = Type const&; using const_reference = Type const&;
protected: protected:
pointer p_data; pointer p_data;
darray<TreeNode*> p_descendants; darray<TreeNode*> p_descendants;
TreeNode* p_ancestor; TreeNode* p_ancestor;
public: public:
friend constexpr friend constexpr
void swap(TreeNode& main, TreeNode& other) noexcept void swap(TreeNode& main, TreeNode& other) noexcept
{ {
using std::swap; using std::swap;
swap(main.p_data, other.p_data); swap(main.p_data, other.p_data);
swap(main.p_descendants, other.p_descendants); swap(main.p_descendants, other.p_descendants);
swap(main.p_ancestor, other.p_ancestor); swap(main.p_ancestor, other.p_ancestor);
} }
inline inline
TreeNode() : TreeNode() :
p_data {new value_type {}}, p_data {new value_type {}},
p_descendants {}, p_descendants {},
p_ancestor {} p_ancestor {}
{} {}
inline inline
TreeNode(const TreeNode& node) : TreeNode(const TreeNode& node) :
p_data {new value_type {*node.p_data}}, p_data {new value_type {*node.p_data}},
p_descendants {}, p_descendants {},
p_ancestor {} p_ancestor {}
{} {}
inline inline
TreeNode(TreeNode&& node) noexcept : TreeNode(TreeNode&& node) noexcept :
p_data {}, p_data {},
p_descendants {}, p_descendants {},
p_ancestor {} p_ancestor {}
{ {
swap(*this, node); swap(*this, node);
/*std::swap(p_data, node.p_data); /*std::swap(p_data, node.p_data);
std::swap(p_descendants, node.p_descendants); std::swap(p_descendants, node.p_descendants);
std::swap(p_ancestor, node.p_ancestor);*/ std::swap(p_ancestor, node.p_ancestor);*/
} }
inline inline
TreeNode& operator=(TreeNode other) TreeNode& operator=(TreeNode other)
{ {
swap(*this, other); swap(*this, other);
return *this; return *this;
} }
inline explicit inline explicit
TreeNode(const value_type& data) : TreeNode(const value_type& data) :
p_data {new value_type {data}}, p_data {new value_type {data}},
p_descendants {}, p_descendants {},
p_ancestor {} p_ancestor {}
{} {}
inline inline
TreeNode(const value_type& data, const darray<TreeNode*>& descendants, TreeNode* ancestor) : TreeNode(const value_type& data, const darray<TreeNode*>& descendants, TreeNode* ancestor) :
p_data {new value_type {data}}, p_data {new value_type {data}},
p_descendants {descendants}, p_descendants {descendants},
p_ancestor {ancestor} p_ancestor {ancestor}
{ {
for (auto descendant : p_descendants) for (auto descendant : p_descendants)
descendant->ancestor(this); descendant->ancestor(this);
} }
inline inline
TreeNode(const value_type& data, const darray<TreeNode*>& descendants) : TreeNode(const value_type& data, const darray<TreeNode*>& descendants) :
p_data {new value_type {data}}, p_data {new value_type {data}},
p_descendants {descendants}, p_descendants {descendants},
p_ancestor {} p_ancestor {}
{ {
for (auto descendant : p_descendants) for (auto descendant : p_descendants)
descendant->ancestor(this); descendant->ancestor(this);
} }
virtual virtual
~TreeNode() ~TreeNode()
{ {
delete p_data; delete p_data;
//delete p_ancestor; //delete p_ancestor;
} }
// Member functions // Member functions
inline inline
pointer data() pointer data()
{ {
return p_data; return p_data;
} }
inline inline
void ancestor(TreeNode* node) void ancestor(TreeNode* node)
{ {
p_ancestor = node; p_ancestor = node;
} }
inline inline
TreeNode* ancestor() TreeNode* ancestor()
{ {
return p_ancestor; return p_ancestor;
} }
inline inline
void descendants(const darray<TreeNode*>& descendants) void descendants(const darray<TreeNode*>& descendants)
{ {
p_descendants = descendants; p_descendants = descendants;
} }
inline inline
darray<TreeNode*>& descendants() darray<TreeNode*>& descendants()
{ {
return p_descendants; return p_descendants;
} }
darray<TreeNode*> traverse_descendants() darray<TreeNode*> traverse_descendants()
{ {
std::function<darray<TreeNode*>(TreeNode*)> collect = [&](TreeNode* node) std::function<darray<TreeNode*>(TreeNode*)> collect = [&](TreeNode* node)
{ {
darray<TreeNode*> ds; darray<TreeNode*> ds;
if (!node->descendants().is_empty()) if (!node->descendants().is_empty())
{ {
for (TreeNode* dnode: node->descendants()) for (TreeNode* dnode: node->descendants())
{ {
ds.push(dnode); ds.push(dnode);
if (!dnode->descendants().is_empty()) if (!dnode->descendants().is_empty())
ds.push(collect(dnode)); ds.push(collect(dnode));
} }
} }
return ds; return ds;
}; };
return collect(this); return collect(this);
} }
darray<TreeNode*> traverse_ancestors() darray<TreeNode*> traverse_ancestors()
{ {
std::function<darray<TreeNode*>(TreeNode*)> collect = [&](TreeNode* node) std::function<darray<TreeNode*>(TreeNode*)> collect = [&](TreeNode* node)
{ {
darray<TreeNode*> ds; darray<TreeNode*> ds;
if (node->p_ancestor) if (node->p_ancestor)
{ {
ds.push(node); ds.push(node);
ds.push(collect(node->p_ancestor)); ds.push(collect(node->p_ancestor));
} }
return ds; return ds;
}; };
return collect(this); return collect(this);
} }
}; };
} // end namespace hpr } // end namespace hpr

View File

@ -1,63 +1,63 @@
#pragma once #pragma once
#include <exception> #include <exception>
#include <string> #include <string>
#include <source_location> #include <source_location>
#include <sstream> #include <sstream>
#include <utility> #include <utility>
#include <vector> #include <vector>
namespace hpr namespace hpr
{ {
class Exception : public std::exception class Exception : public std::exception
{ {
protected: protected:
std::string p_message; std::string p_message;
public: public:
inline explicit inline explicit
Exception(std::source_location location = std::source_location::current()) : Exception(std::source_location location = std::source_location::current()) :
p_message {} p_message {}
{ {
std::stringstream _message; std::stringstream _message;
_message << "\t" << p_message _message << "\t" << p_message
<< "\n where:\t\t" << location.file_name() << ":" << location.line() << ":" << location.column() << "\n where:\t\t" << location.file_name() << ":" << location.line() << ":" << location.column()
<< "\n function:\t" << location.function_name(); << "\n function:\t" << location.function_name();
p_message = _message.str(); p_message = _message.str();
} }
inline explicit inline explicit
Exception(const std::string& message, std::source_location location = std::source_location::current()) : Exception(const std::string& message, std::source_location location = std::source_location::current()) :
p_message {message} p_message {message}
{ {
std::stringstream _message; std::stringstream _message;
_message << "\t" << p_message _message << "\t" << p_message
<< "\n where:\t" << location.file_name() << ":" << location.line() << ":" << location.column() << "\n where:\t" << location.file_name() << ":" << location.line() << ":" << location.column()
<< "\n function:\t" << location.function_name(); << "\n function:\t" << location.function_name();
p_message = _message.str(); p_message = _message.str();
} }
[[nodiscard]] [[nodiscard]]
const char* what() const noexcept override { const char* what() const noexcept override {
std::vector<float> vv; std::vector<float> vv;
return p_message.data(); return p_message.data();
} }
}; };
struct OutOfRange : public Exception struct OutOfRange : public Exception
{ {
inline explicit OutOfRange(std::source_location location = std::source_location::current()) : Exception {"Out of range", location} {} inline explicit OutOfRange(std::source_location location = std::source_location::current()) : Exception {"Out of range", location} {}
inline explicit OutOfRange(const std::string& message, std::source_location location = std::source_location::current()) : Exception {message, location} {} inline explicit OutOfRange(const std::string& message, std::source_location location = std::source_location::current()) : Exception {message, location} {}
}; };
struct LengthError : public Exception struct LengthError : public Exception
{ {
inline explicit LengthError(std::source_location location = std::source_location::current()) : Exception {"Length error", location} {} inline explicit LengthError(std::source_location location = std::source_location::current()) : Exception {"Length error", location} {}
inline explicit LengthError(const std::string& message, std::source_location location = std::source_location::current()) : Exception {message, location} {} inline explicit LengthError(const std::string& message, std::source_location location = std::source_location::current()) : Exception {message, location} {}
}; };
} // end namespace hpr } // end namespace hpr

View File

@ -1,5 +1,6 @@
#include <hpr/exception.hpp> #include <hpr/exception.hpp>
#include <hpr/numeric.hpp> #include <hpr/numeric.hpp>
#include <hpr/container.hpp> #include <hpr/container.hpp>
#include <hpr/math.hpp> #include <hpr/math.hpp>
#include <hpr/shape.hpp>

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include <hpr/math/vector.hpp> #include <hpr/math/vector.hpp>
#include <hpr/math/quaternion.hpp> #include <hpr/math/quaternion.hpp>
#include <hpr/math/matrix.hpp> #include <hpr/math/matrix.hpp>

File diff suppressed because it is too large Load Diff

View File

@ -1,290 +1,290 @@
#pragma once #pragma once
#include <hpr/math/vector.hpp> #include <hpr/math/vector.hpp>
#include <hpr/exception.hpp> #include <hpr/exception.hpp>
namespace hpr namespace hpr
{ {
// forward declarations // forward declarations
class Quaternion; class Quaternion;
inline inline
Quaternion inverse(const Quaternion& q); Quaternion inverse(const Quaternion& q);
inline inline
Quaternion operator*(const Quaternion& lhs, const Quaternion& rhs); Quaternion operator*(const Quaternion& lhs, const Quaternion& rhs);
// aliases // aliases
using quat = Quaternion; using quat = Quaternion;
// class declaration // class declaration
class Quaternion class Quaternion
{ {
public: public:
enum RotationSequence enum RotationSequence
{ {
ZYX, ZYZ, ZXY, ZXZ, YXZ, YXY, YZX, YZY, XYZ, XYX, XZY, XZX ZYX, ZYZ, ZXY, ZXZ, YXZ, YXY, YZX, YZY, XYZ, XYX, XZY, XZX
}; };
protected: protected:
scalar p_real; scalar p_real;
vec3 p_imag; vec3 p_imag;
public: public:
inline inline
Quaternion() : Quaternion() :
p_real{}, p_real{},
p_imag{} p_imag{}
{} {}
inline inline
Quaternion(const scalar real, const vec3& imag) : Quaternion(const scalar real, const vec3& imag) :
p_real {real}, p_real {real},
p_imag {imag} p_imag {imag}
{} {}
inline explicit inline explicit
Quaternion(const scalar real) : Quaternion(const scalar real) :
p_real {real}, p_real {real},
p_imag {} p_imag {}
{} {}
inline explicit inline explicit
Quaternion(const vec3& imag) : Quaternion(const vec3& imag) :
p_real {}, p_real {},
p_imag {imag} p_imag {imag}
{} {}
inline inline
Quaternion(const vec3& vs, const scalar& theta) : Quaternion(const vec3& vs, const scalar& theta) :
p_real {cos(0.5 * theta)}, p_real {cos(0.5 * theta)},
p_imag {sin(0.5 * theta) * vs / mag(vs)} p_imag {sin(0.5 * theta) * vs / mag(vs)}
{} {}
static inline static inline
Quaternion unit(const vec3& vs) Quaternion unit(const vec3& vs)
{ {
return Quaternion(sqrt(1 - norm(vs)), vs); return Quaternion(sqrt(1 - norm(vs)), vs);
} }
inline inline
Quaternion(const RotationSequence rs, const vec3& angles) Quaternion(const RotationSequence rs, const vec3& angles)
{ {
switch (rs) switch (rs)
{ {
case XYZ: case XYZ:
*this = Quaternion(vec3(0, 1, 0), angles[0]) * *this = Quaternion(vec3(0, 1, 0), angles[0]) *
Quaternion(vec3(0, 1, 0), angles[1]) * Quaternion(vec3(0, 1, 0), angles[1]) *
Quaternion(vec3(0, 0, 1), angles[2]); Quaternion(vec3(0, 0, 1), angles[2]);
break; break;
default: default:
throw std::runtime_error("Unknown rotation sequence"); throw std::runtime_error("Unknown rotation sequence");
} }
} }
inline inline
scalar real() const scalar real() const
{ {
return p_real; return p_real;
} }
inline inline
scalar& real() scalar& real()
{ {
return p_real; return p_real;
} }
inline inline
vec3 imag() const vec3 imag() const
{ {
return p_imag; return p_imag;
} }
inline inline
vec3& imag() vec3& imag()
{ {
return p_imag; return p_imag;
} }
inline inline
scalar& operator[](Size n) scalar& operator[](Size n)
{ {
if (n > 3) if (n > 3)
throw hpr::OutOfRange(); throw hpr::OutOfRange();
if (n == 0) if (n == 0)
return p_real; return p_real;
else else
return p_imag[n - 1]; return p_imag[n - 1];
} }
inline inline
scalar operator[](Size n) const scalar operator[](Size n) const
{ {
if (n > 3) if (n > 3)
throw hpr::OutOfRange(); throw hpr::OutOfRange();
if (n == 0) if (n == 0)
return p_real; return p_real;
else else
return p_imag[n - 1]; return p_imag[n - 1];
} }
inline inline
void operator+=(const Quaternion& q) void operator+=(const Quaternion& q)
{ {
p_real += q.p_real; p_real += q.p_real;
p_imag += q.p_imag; p_imag += q.p_imag;
} }
inline inline
void operator-=(const Quaternion& q) void operator-=(const Quaternion& q)
{ {
p_real -= q.p_real; p_real -= q.p_real;
p_imag -= q.p_imag; p_imag -= q.p_imag;
} }
inline inline
void operator*=(const Quaternion& q) void operator*=(const Quaternion& q)
{ {
scalar temp = p_real; scalar temp = p_real;
p_real = p_real * q.p_real - dot(p_imag, q.p_imag); p_real = p_real * q.p_real - dot(p_imag, q.p_imag);
p_imag = temp * q.p_imag + q.p_real * p_imag + cross(p_imag, q.p_imag); p_imag = temp * q.p_imag + q.p_real * p_imag + cross(p_imag, q.p_imag);
} }
inline inline
void operator/=(const Quaternion& q) void operator/=(const Quaternion& q)
{ {
operator*=(inverse(q)); operator*=(inverse(q));
} }
inline inline
void operator*=(const scalar s) void operator*=(const scalar s)
{ {
p_real *= s; p_real *= s;
p_imag *= s; p_imag *= s;
} }
inline inline
void operator/=(const scalar s) void operator/=(const scalar s)
{ {
p_real /= s; p_real /= s;
p_imag /= s; p_imag /= s;
} }
}; };
inline inline
bool equal(const Quaternion& lhs, const Quaternion& rhs) bool equal(const Quaternion& lhs, const Quaternion& rhs)
{ {
return lhs.real() == rhs.real() && lhs.imag() == rhs.imag(); return lhs.real() == rhs.real() && lhs.imag() == rhs.imag();
} }
inline inline
bool operator==(const Quaternion& lhs, const Quaternion& rhs) bool operator==(const Quaternion& lhs, const Quaternion& rhs)
{ {
return equal(lhs, rhs); return equal(lhs, rhs);
} }
inline inline
bool operator!=(const Quaternion& lhs, const Quaternion& rhs) bool operator!=(const Quaternion& lhs, const Quaternion& rhs)
{ {
return !equal(lhs, rhs); return !equal(lhs, rhs);
} }
inline inline
Quaternion operator+(const Quaternion& lhs, const Quaternion& rhs) Quaternion operator+(const Quaternion& lhs, const Quaternion& rhs)
{ {
return {lhs.real() + rhs.real(), lhs.imag() + rhs.imag()}; return {lhs.real() + rhs.real(), lhs.imag() + rhs.imag()};
} }
inline inline
Quaternion operator-(const Quaternion& q) Quaternion operator-(const Quaternion& q)
{ {
return {q.real(), q.imag()}; return {q.real(), q.imag()};
} }
inline inline
Quaternion operator-(const Quaternion& lhs, const Quaternion& rhs) Quaternion operator-(const Quaternion& lhs, const Quaternion& rhs)
{ {
return {lhs.real() - rhs.real(), lhs.imag() - rhs.imag()}; return {lhs.real() - rhs.real(), lhs.imag() - rhs.imag()};
} }
inline inline
Quaternion operator*(const Quaternion& lhs, const Quaternion& rhs) Quaternion operator*(const Quaternion& lhs, const Quaternion& rhs)
{ {
return { return {
lhs.real() * rhs.real() - dot(lhs.imag(), rhs.imag()), lhs.real() * rhs.real() - dot(lhs.imag(), rhs.imag()),
lhs.real() * rhs.imag() + rhs.real() * lhs.imag() + cross(lhs.imag(), rhs.imag()) lhs.real() * rhs.imag() + rhs.real() * lhs.imag() + cross(lhs.imag(), rhs.imag())
}; };
} }
inline inline
Quaternion operator/(const Quaternion& lhs, const Quaternion& rhs) Quaternion operator/(const Quaternion& lhs, const Quaternion& rhs)
{ {
return lhs * inverse(rhs); return lhs * inverse(rhs);
} }
inline inline
Quaternion operator*(const scalar s, const Quaternion& q) Quaternion operator*(const scalar s, const Quaternion& q)
{ {
return {s * q.real(), s * q.imag()}; return {s * q.real(), s * q.imag()};
} }
inline inline
Quaternion operator*(const Quaternion& q, const scalar s) Quaternion operator*(const Quaternion& q, const scalar s)
{ {
return {q.real() * s, q.imag() * s}; return {q.real() * s, q.imag() * s};
} }
inline inline
Quaternion operator/(const Quaternion& q, const scalar s) Quaternion operator/(const Quaternion& q, const scalar s)
{ {
return {q.real() / s, q.imag() / s}; return {q.real() / s, q.imag() / s};
} }
inline inline
scalar norm(const Quaternion& q) scalar norm(const Quaternion& q)
{ {
return sqrt(pow(q.real(), 2) + dot(q.imag(), q.imag())); return sqrt(pow(q.real(), 2) + dot(q.imag(), q.imag()));
} }
inline inline
Quaternion conjugate(const Quaternion& q) Quaternion conjugate(const Quaternion& q)
{ {
return {q.real(), -q.imag()}; return {q.real(), -q.imag()};
} }
inline inline
Quaternion inverse(const Quaternion& q) Quaternion inverse(const Quaternion& q)
{ {
return conjugate(q) / pow(norm(q), 2); return conjugate(q) / pow(norm(q), 2);
} }
inline inline
Quaternion normalize(const Quaternion& q) Quaternion normalize(const Quaternion& q)
{ {
return q / norm(q); return q / norm(q);
} }
inline inline
vec3 rotate(const vec3& point, const vec3& axis, const scalar& angle) vec3 rotate(const vec3& point, const vec3& axis, const scalar& angle)
{ {
Quaternion p {point}; Quaternion p {point};
Quaternion q {normalize(axis), angle}; Quaternion q {normalize(axis), angle};
return (q * p * inverse(q)).imag(); return (q * p * inverse(q)).imag();
} }
void decompose(const Quaternion& q, vec3& axis, scalar& angle) void decompose(const Quaternion& q, vec3& axis, scalar& angle)
{ {
const scalar qnorm = norm(q.imag()); const scalar qnorm = norm(q.imag());
axis = q.imag() / qnorm; axis = q.imag() / qnorm;
angle = 2 * atan2(qnorm, q.real()); angle = 2 * atan2(qnorm, q.real());
} }
} // end namespace hpr } // end namespace hpr

View File

@ -1,321 +1,321 @@
#pragma once #pragma once
#include <hpr/numeric.hpp> #include <hpr/numeric.hpp>
#include <hpr/container/static_array.hpp> #include <hpr/container/static_array.hpp>
namespace hpr namespace hpr
{ {
// forward declarations // forward declarations
template <IsReal T, Size S> requires (S >= 0) template <IsReal T, Size S> requires (S >= 0)
class Vector; class Vector;
template <IsReal T, Size S> template <IsReal T, Size S>
using SubVector = typename std::conditional<S >= 2, Vector<T, S - 1>, Vector<T, 1>>::type; using SubVector = typename std::conditional<S >= 2, Vector<T, S - 1>, Vector<T, 1>>::type;
// type traits // type traits
template <typename T> template <typename T>
struct is_vector : public std::false_type {}; struct is_vector : public std::false_type {};
template <typename T, Size S> template <typename T, Size S>
struct is_vector<Vector<T, S>> : public std::true_type {}; struct is_vector<Vector<T, S>> : public std::true_type {};
// concepts // concepts
template <typename T> template <typename T>
concept IsVector = is_vector<T>::value; concept IsVector = is_vector<T>::value;
// aliases // aliases
template <typename Type, Size S> template <typename Type, Size S>
using vec = Vector<Type, S>; using vec = Vector<Type, S>;
using vec2 = Vector<scalar, 2>; using vec2 = Vector<scalar, 2>;
using vec3 = Vector<scalar, 3>; using vec3 = Vector<scalar, 3>;
using vec4 = Vector<scalar, 4>; using vec4 = Vector<scalar, 4>;
template <IsReal Type, Size S> requires (S >= 0) template <IsReal Type, Size S> requires (S >= 0)
class Vector : public StaticArray<Type, S> class Vector : public StaticArray<Type, S>
{ {
using base = StaticArray<Type, S>; using base = StaticArray<Type, S>;
public: public:
using value_type = Type; using value_type = Type;
using size_type = Size; using size_type = Size;
using pointer = Type*; using pointer = Type*;
using reference = Type&; using reference = Type&;
using iterator = Iterator<Type>; using iterator = Iterator<Type>;
using const_iterator = Iterator<const Type>; using const_iterator = Iterator<const Type>;
public: public:
//! null constructor //! null constructor
constexpr constexpr
Vector() : Vector() :
base {} base {}
{} {}
//! copy constructor //! copy constructor
constexpr constexpr
Vector(const Vector& vs) : Vector(const Vector& vs) :
base {static_cast<base>(vs)} base {static_cast<base>(vs)}
{} {}
//! move constructor //! move constructor
constexpr constexpr
Vector(Vector&& vs) noexcept : Vector(Vector&& vs) noexcept :
base {std::forward<base>(static_cast<base>(vs))} base {std::forward<base>(static_cast<base>(vs))}
{} {}
//! copy assignment operator //! copy assignment operator
constexpr constexpr
Vector& operator=(const Vector& vs) Vector& operator=(const Vector& vs)
{ {
base::operator=(vs); base::operator=(vs);
return *this; return *this;
} }
//! move assignment operator //! move assignment operator
constexpr constexpr
Vector& operator=(Vector&& vs) noexcept Vector& operator=(Vector&& vs) noexcept
{ {
swap(*this, vs); swap(*this, vs);
return *this; return *this;
} }
//! destructor //! destructor
virtual virtual
~Vector() = default; ~Vector() = default;
//! copy constructor from base //! copy constructor from base
constexpr constexpr
Vector(const base& arr) : Vector(const base& arr) :
base {arr} base {arr}
{} {}
//! move constructor from base //! move constructor from base
constexpr constexpr
Vector(base&& arr) : Vector(base&& arr) :
base {std::forward<base>(arr)} base {std::forward<base>(arr)}
{} {}
//! construct from iterators //! construct from iterators
constexpr constexpr
Vector(typename base::iterator start, typename base::iterator end) : Vector(typename base::iterator start, typename base::iterator end) :
base {start, end} base {start, end}
{} {}
//! construct from constant iterators //! construct from constant iterators
constexpr constexpr
Vector(typename base::const_iterator start, typename base::const_iterator end) : Vector(typename base::const_iterator start, typename base::const_iterator end) :
base {start, end} base {start, end}
{} {}
//! construct from initializer list //! construct from initializer list
constexpr constexpr
Vector(std::initializer_list<value_type> list) : Vector(std::initializer_list<value_type> list) :
base {list} base {list}
{} {}
//! copy constructor with variadic args //! copy constructor with variadic args
template <IsReal... Args> template <IsReal... Args>
constexpr constexpr
Vector(const value_type& v, const Args& ...args) requires (S == 1 + sizeof...(args)): Vector(const value_type& v, const Args& ...args) requires (S == 1 + sizeof...(args)):
base {v, static_cast<value_type>(args)...} base {v, static_cast<value_type>(args)...}
{} {}
//! move constructor with variadic args //! move constructor with variadic args
template <IsReal... Args> template <IsReal... Args>
constexpr constexpr
Vector(value_type&& v, Args&& ...args) requires (S == 1 + sizeof...(args)): Vector(value_type&& v, Args&& ...args) requires (S == 1 + sizeof...(args)):
base {v, static_cast<value_type>(std::forward<Args>(args))...} base {v, static_cast<value_type>(std::forward<Args>(args))...}
{} {}
//! copy constructor with sub vector and value //! copy constructor with sub vector and value
constexpr constexpr
Vector(const SubVector<Type, S>& svs, const value_type& v) requires (S >= 1): Vector(const SubVector<Type, S>& svs, const value_type& v) requires (S >= 1):
base {} base {}
{ {
for (auto n = 0; n < svs.size(); ++n) for (auto n = 0; n < svs.size(); ++n)
(*this)[n] = svs[n]; (*this)[n] = svs[n];
(*this)[svs.size()] = v; (*this)[svs.size()] = v;
} }
//! copy constructor from greater vector //! copy constructor from greater vector
template <Size GS> requires (GS > S) template <Size GS> requires (GS > S)
constexpr explicit constexpr explicit
Vector(const Vector<Type, GS>& vs) : Vector(const Vector<Type, GS>& vs) :
base {vs.begin(), vs.begin() + S} base {vs.begin(), vs.begin() + S}
{} {}
}; };
// global operators // global operators
template <IsReal T, Size S> inline Vector<T, S> operator+(const Vector<T, S>& lhs) { Vector<T, S> vs; for (Size n = 0; n < S; ++n) vs[n] = lhs[n]; return vs; } template <IsReal T, Size S> inline Vector<T, S> operator+(const Vector<T, S>& lhs) { Vector<T, S> vs; for (Size n = 0; n < S; ++n) vs[n] = lhs[n]; return vs; }
template <IsReal T, Size S> inline Vector<T, S> operator-(const Vector<T, S>& lhs) { Vector<T, S> vs; for (Size n = 0; n < S; ++n) vs[n] = -lhs[n]; return vs; } template <IsReal T, Size S> inline Vector<T, S> operator-(const Vector<T, S>& lhs) { Vector<T, S> vs; for (Size n = 0; n < S; ++n) vs[n] = -lhs[n]; return vs; }
template <IsReal T, Size S> inline Vector<T, S>& operator+=(Vector<T, S>& lhs, const Vector<T, S>& rhs) { for (Size n = 0; n < S; ++n) lhs[n] += rhs[n]; return lhs; } template <IsReal T, Size S> inline Vector<T, S>& operator+=(Vector<T, S>& lhs, const Vector<T, S>& rhs) { for (Size n = 0; n < S; ++n) lhs[n] += rhs[n]; return lhs; }
template <IsReal T, Size S> inline Vector<T, S>& operator-=(Vector<T, S>& lhs, const Vector<T, S>& rhs) { for (Size n = 0; n < S; ++n) lhs[n] -= rhs[n]; return lhs; } template <IsReal T, Size S> inline Vector<T, S>& operator-=(Vector<T, S>& lhs, const Vector<T, S>& rhs) { for (Size n = 0; n < S; ++n) lhs[n] -= rhs[n]; return lhs; }
template <IsReal T, Size S> inline Vector<T, S>& operator*=(Vector<T, S>& lhs, const Vector<T, S>& rhs) { for (Size n = 0; n < S; ++n) lhs[n] *= rhs[n]; return lhs; } template <IsReal T, Size S> inline Vector<T, S>& operator*=(Vector<T, S>& lhs, const Vector<T, S>& rhs) { for (Size n = 0; n < S; ++n) lhs[n] *= rhs[n]; return lhs; }
template <IsReal T, Size S> inline Vector<T, S>& operator/=(Vector<T, S>& lhs, const Vector<T, S>& rhs) { for (Size n = 0; n < S; ++n) lhs[n] /= rhs[n]; return lhs; } template <IsReal T, Size S> inline Vector<T, S>& operator/=(Vector<T, S>& lhs, const Vector<T, S>& rhs) { for (Size n = 0; n < S; ++n) lhs[n] /= rhs[n]; return lhs; }
template <IsReal T, Size S> inline Vector<T, S> operator+(const Vector<T, S>& lhs, const Vector<T, S>& rhs) { Vector<T, S> vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] += rhs[n]; return vs; } template <IsReal T, Size S> inline Vector<T, S> operator+(const Vector<T, S>& lhs, const Vector<T, S>& rhs) { Vector<T, S> vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] += rhs[n]; return vs; }
template <IsReal T, Size S> inline Vector<T, S> operator-(const Vector<T, S>& lhs, const Vector<T, S>& rhs) { Vector<T, S> vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] -= rhs[n]; return vs; } template <IsReal T, Size S> inline Vector<T, S> operator-(const Vector<T, S>& lhs, const Vector<T, S>& rhs) { Vector<T, S> vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] -= rhs[n]; return vs; }
template <IsReal T, Size S> inline Vector<T, S> operator*(const Vector<T, S>& lhs, const Vector<T, S>& rhs) { Vector<T, S> vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] *= rhs[n]; return vs; } template <IsReal T, Size S> inline Vector<T, S> operator*(const Vector<T, S>& lhs, const Vector<T, S>& rhs) { Vector<T, S> vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] *= rhs[n]; return vs; }
template <IsReal T, Size S> inline Vector<T, S> operator/(const Vector<T, S>& lhs, const Vector<T, S>& rhs) { Vector<T, S> vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] /= rhs[n]; return vs; } template <IsReal T, Size S> inline Vector<T, S> operator/(const Vector<T, S>& lhs, const Vector<T, S>& rhs) { Vector<T, S> vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] /= rhs[n]; return vs; }
template <IsReal T, Size S> inline bool operator==(const Vector<T, S>& lhs, const Vector<T, S>& rhs) { for (Size n = 0; n < S; ++n) if (lhs[n] != rhs[n]) return false; return true; } template <IsReal T, Size S> inline bool operator==(const Vector<T, S>& lhs, const Vector<T, S>& rhs) { for (Size n = 0; n < S; ++n) if (lhs[n] != rhs[n]) return false; return true; }
template <IsReal T, Size S> inline bool operator!=(const Vector<T, S>& lhs, const Vector<T, S>& rhs) { for (Size n = 0; n < S; ++n) if (lhs[n] == rhs[n]) return false; return true; } template <IsReal T, Size S> inline bool operator!=(const Vector<T, S>& lhs, const Vector<T, S>& rhs) { for (Size n = 0; n < S; ++n) if (lhs[n] == rhs[n]) return false; return true; }
template <IsReal T, Size S> inline Vector<T, S>& operator+=(Vector<T, S>& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] += rhs; return lhs; } template <IsReal T, Size S> inline Vector<T, S>& operator+=(Vector<T, S>& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] += rhs; return lhs; }
template <IsReal T, Size S> inline Vector<T, S>& operator-=(Vector<T, S>& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] -= rhs; return lhs; } template <IsReal T, Size S> inline Vector<T, S>& operator-=(Vector<T, S>& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] -= rhs; return lhs; }
template <IsReal T, Size S> inline Vector<T, S>& operator*=(Vector<T, S>& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] *= rhs; return lhs; } template <IsReal T, Size S> inline Vector<T, S>& operator*=(Vector<T, S>& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] *= rhs; return lhs; }
template <IsReal T, Size S> inline Vector<T, S>& operator/=(Vector<T, S>& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] /= rhs; return lhs; } template <IsReal T, Size S> inline Vector<T, S>& operator/=(Vector<T, S>& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] /= rhs; return lhs; }
template <IsReal T, Size S> inline Vector<T, S> operator+(const Vector<T, S>& lhs, const T& rhs) { Vector<T, S> vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] += rhs; return vs; } template <IsReal T, Size S> inline Vector<T, S> operator+(const Vector<T, S>& lhs, const T& rhs) { Vector<T, S> vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] += rhs; return vs; }
template <IsReal T, Size S> inline Vector<T, S> operator-(const Vector<T, S>& lhs, const T& rhs) { Vector<T, S> vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] -= rhs; return vs; } template <IsReal T, Size S> inline Vector<T, S> operator-(const Vector<T, S>& lhs, const T& rhs) { Vector<T, S> vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] -= rhs; return vs; }
template <IsReal T, IsReal T2, Size S> inline Vector<T, S> operator*(const Vector<T, S>& lhs, const T2& rhs) { Vector<T, S> vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] *= static_cast<T>(rhs); return vs; } template <IsReal T, IsReal T2, Size S> inline Vector<T, S> operator*(const Vector<T, S>& lhs, const T2& rhs) { Vector<T, S> vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] *= static_cast<T>(rhs); return vs; }
template <IsReal T, IsReal T2, Size S> inline Vector<T, S> operator/(const Vector<T, S>& lhs, const T2& rhs) { Vector<T, S> vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] /= static_cast<T>(rhs); return vs; } template <IsReal T, IsReal T2, Size S> inline Vector<T, S> operator/(const Vector<T, S>& lhs, const T2& rhs) { Vector<T, S> vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] /= static_cast<T>(rhs); return vs; }
template <IsReal T, Size S> inline Vector<T, S> operator+(const T& lhs, const Vector<T, S>& rhs) { Vector<T, S> vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] += lhs; return vs; } template <IsReal T, Size S> inline Vector<T, S> operator+(const T& lhs, const Vector<T, S>& rhs) { Vector<T, S> vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] += lhs; return vs; }
template <IsReal T, Size S> inline Vector<T, S> operator-(const T& lhs, const Vector<T, S>& rhs) { Vector<T, S> vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] -= lhs; return vs; } template <IsReal T, Size S> inline Vector<T, S> operator-(const T& lhs, const Vector<T, S>& rhs) { Vector<T, S> vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] -= lhs; return vs; }
template <IsReal T, Size S> inline Vector<T, S> operator*(const T& lhs, const Vector<T, S>& rhs) { Vector<T, S> vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] *= lhs; return vs; } template <IsReal T, Size S> inline Vector<T, S> operator*(const T& lhs, const Vector<T, S>& rhs) { Vector<T, S> vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] *= lhs; return vs; }
template <IsReal T, Size S> inline Vector<T, S> operator/(const T& lhs, const Vector<T, S>& rhs) { Vector<T, S> vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] /= lhs; return vs; } template <IsReal T, Size S> inline Vector<T, S> operator/(const T& lhs, const Vector<T, S>& rhs) { Vector<T, S> vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] /= lhs; return vs; }
// boolean operations // boolean operations
template <typename Type, Size S> template <typename Type, Size S>
inline inline
Vector<bool, S> equal(const Vector<Type, S>& lhs, const Vector<Type, S>& rhs, const scalar& precision = hpr::precision()) Vector<bool, S> equal(const Vector<Type, S>& lhs, const Vector<Type, S>& rhs, const scalar& precision = hpr::precision())
{ {
Vector<bool, S> vs; Vector<bool, S> vs;
for (auto n = 0; n < S; ++n) for (auto n = 0; n < S; ++n)
vs[n] = equal(lhs[n], rhs[n], precision); vs[n] = equal(lhs[n], rhs[n], precision);
return vs; return vs;
} }
template <Size S> template <Size S>
inline inline
bool any(const Vector<bool, S>& vs) bool any(const Vector<bool, S>& vs)
{ {
bool res = false; bool res = false;
for (auto e : vs) for (auto e : vs)
res = res || e; res = res || e;
return res; return res;
} }
template <Size S> template <Size S>
inline inline
bool all(const Vector<bool, S>& vs) bool all(const Vector<bool, S>& vs)
{ {
bool res = true; bool res = true;
for (auto e : vs) for (auto e : vs)
res = res && e; res = res && e;
return res; return res;
} }
// per element operations // per element operations
template <typename Type, Size S> template <typename Type, Size S>
inline inline
Vector<Type, S> abs(const Vector<Type, S>& vs) Vector<Type, S> abs(const Vector<Type, S>& vs)
{ {
Vector<Type, S> res; Vector<Type, S> res;
for (auto n = 0; n < S; ++n) for (auto n = 0; n < S; ++n)
res[n] = abs(vs[n]); res[n] = abs(vs[n]);
return res; return res;
} }
template <typename Type, Size S> template <typename Type, Size S>
inline inline
Type sum(const Vector<Type, S>& vs) Type sum(const Vector<Type, S>& vs)
{ {
Type sum {}; Type sum {};
for (const Type& v : vs) for (const Type& v : vs)
sum += v; sum += v;
return sum; return sum;
} }
template <typename Type, Size S> template <typename Type, Size S>
inline inline
Vector<Type, S> pow(const Vector<Type, S>& vs, scalar degree) Vector<Type, S> pow(const Vector<Type, S>& vs, scalar degree)
{ {
Vector<Type, S> res; Vector<Type, S> res;
for (auto n = 0; n < S; ++n) for (auto n = 0; n < S; ++n)
res[n] = pow(vs[n], degree); res[n] = pow(vs[n], degree);
return res; return res;
} }
// vector operations // vector operations
template <typename Type, Size S> template <typename Type, Size S>
inline inline
Type norm(const Vector<Type, S>& vs) Type norm(const Vector<Type, S>& vs)
{ {
return sqrt(sum(pow(abs(vs), 2))); return sqrt(sum(pow(abs(vs), 2)));
} }
template <typename Type, Size S> template <typename Type, Size S>
inline inline
Type dot(const Vector<Type, S>& lhs, const Vector<Type, S>& rhs) Type dot(const Vector<Type, S>& lhs, const Vector<Type, S>& rhs)
{ {
return sum(lhs * rhs); return sum(lhs * rhs);
} }
template <typename Type, Size S> template <typename Type, Size S>
inline inline
Type length(const Vector<Type, S>& vs) Type length(const Vector<Type, S>& vs)
{ {
return sqrt(dot(vs, vs)); return sqrt(dot(vs, vs));
} }
template <typename Type, Size S> template <typename Type, Size S>
inline inline
Type mag(const Vector<Type, S>& vs) Type mag(const Vector<Type, S>& vs)
{ {
return length(vs); return length(vs);
} }
template <typename Type, Size S> template <typename Type, Size S>
inline inline
Type distance(const Vector<Type, S>& vs1, const Vector<Type, S>& vs2) Type distance(const Vector<Type, S>& vs1, const Vector<Type, S>& vs2)
{ {
return length(vs1 - vs2); return length(vs1 - vs2);
} }
template <typename Type, Size S> template <typename Type, Size S>
inline inline
Vector<Type, S> normalize(const Vector<Type, S>& vs) Vector<Type, S> normalize(const Vector<Type, S>& vs)
{ {
return vs * isqrt(dot(vs, vs)); return vs * isqrt(dot(vs, vs));
} }
template <typename Type> template <typename Type>
inline inline
Type angle(const Vector<Type, 3>& lhs, const Vector<Type, 3>& rhs) Type angle(const Vector<Type, 3>& lhs, const Vector<Type, 3>& rhs)
{ {
scalar cos = dot(lhs, rhs) / (norm(lhs) * norm(rhs)); scalar cos = dot(lhs, rhs) / (norm(lhs) * norm(rhs));
return acos(cos); //clip(cos, -1., 1.)); return acos(cos); //clip(cos, -1., 1.));
} }
// vector 3 operations // vector 3 operations
template <typename Type> template <typename Type>
inline inline
Vector<Type, 3> cross(const Vector<Type, 3>& lhs, const Vector<Type, 3>& rhs) Vector<Type, 3> cross(const Vector<Type, 3>& lhs, const Vector<Type, 3>& rhs)
{ {
return Vector<Type, 3>( return Vector<Type, 3>(
lhs[1] * rhs[2] - lhs[2] * rhs[1], lhs[1] * rhs[2] - lhs[2] * rhs[1],
lhs[2] * rhs[0] - lhs[0] * rhs[2], lhs[2] * rhs[0] - lhs[0] * rhs[2],
lhs[0] * rhs[1] - lhs[1] * rhs[0] lhs[0] * rhs[1] - lhs[1] * rhs[0]
); );
} }
} // end namespace hpr } // end namespace hpr

View File

@ -1,305 +1,305 @@
#pragma once #pragma once
#include <type_traits> #include <type_traits>
#include <cmath> #include <cmath>
#include <limits> #include <limits>
#include <numbers> #include <numbers>
#ifdef __MSC_VER #ifdef __MSC_VER
#define HPR_CONSTEXPR #define HPR_CONSTEXPR
#else #else
#define HPR_CONSTEXPR constexpr #define HPR_CONSTEXPR constexpr
#endif #endif
namespace hpr namespace hpr
{ {
using Size = std::size_t; using Size = std::size_t;
template <typename Type> template <typename Type>
struct is_size : public std::integral_constant<bool, std::is_integral<Type>::value && std::is_unsigned<Type>::value> {}; struct is_size : public std::integral_constant<bool, std::is_integral<Type>::value && std::is_unsigned<Type>::value> {};
template <typename Type> template <typename Type>
concept IsSize = is_size<Type>::value || std::convertible_to<Type, Size>; concept IsSize = is_size<Type>::value || std::convertible_to<Type, Size>;
template <typename Type> template <typename Type>
struct is_integer : public std::is_integral<Type> {}; struct is_integer : public std::is_integral<Type> {};
template <typename Type> template <typename Type>
concept IsInteger = is_integer<Type>::value; concept IsInteger = is_integer<Type>::value;
template <typename Type> template <typename Type>
struct is_scalar : public std::is_floating_point<Type> {}; struct is_scalar : public std::is_floating_point<Type> {};
template <typename Type> template <typename Type>
concept IsScalar = is_scalar<Type>::value; concept IsScalar = is_scalar<Type>::value;
template <typename Type> template <typename Type>
concept IsReal = is_integer<Type>::value || is_scalar<Type>::value; concept IsReal = is_integer<Type>::value || is_scalar<Type>::value;
#ifndef HPR_SCALAR #ifndef HPR_SCALAR
#define HPR_SCALAR float #define HPR_SCALAR float
#endif #endif
#ifdef HPR_SCALAR_IMPLEMENTATION #ifdef HPR_SCALAR_IMPLEMENTATION
template <IsScalar T> template <IsScalar T>
class Scalar class Scalar
{ {
public: public:
using type = Scalar<T>; using type = Scalar<T>;
using value_type = T; using value_type = T;
protected: protected:
value_type p_value; value_type p_value;
public: public:
// constructors // constructors
constexpr Scalar() : p_value {} {} constexpr Scalar() : p_value {} {}
template <IsScalar X> constexpr Scalar(const Scalar<X>& value) : p_value {static_cast<value_type>(value.p_value)} {} template <IsScalar X> constexpr Scalar(const Scalar<X>& value) : p_value {static_cast<value_type>(value.p_value)} {}
template <IsReal X> constexpr Scalar(const X& value) : p_value {static_cast<value_type>(value)} {} template <IsReal X> constexpr Scalar(const X& value) : p_value {static_cast<value_type>(value)} {}
template <IsScalar X> constexpr type& operator=(const Scalar<X>& value) { p_value = static_cast<value_type>(value.p_value); return *this; } template <IsScalar X> constexpr type& operator=(const Scalar<X>& value) { p_value = static_cast<value_type>(value.p_value); return *this; }
template <IsReal X> constexpr type& operator=(const X& value) { p_value = static_cast<value_type>(value); return *this; } template <IsReal X> constexpr type& operator=(const X& value) { p_value = static_cast<value_type>(value); return *this; }
virtual constexpr ~Scalar() = default; virtual constexpr ~Scalar() = default;
// conversion // conversion
constexpr operator double() const { return static_cast<double>(p_value); } constexpr operator double() const { return static_cast<double>(p_value); }
constexpr operator float() const { return static_cast<float>(p_value); } constexpr operator float() const { return static_cast<float>(p_value); }
constexpr operator long double() const { return static_cast<long double>(p_value); } constexpr operator long double() const { return static_cast<long double>(p_value); }
constexpr operator bool() const { return static_cast<bool>(p_value); } constexpr operator bool() const { return static_cast<bool>(p_value); }
// access // access
[[nodiscard]] constexpr value_type value() const { return p_value; } [[nodiscard]] constexpr value_type value() const { return p_value; }
constexpr value_type& value() { return p_value; } constexpr value_type& value() { return p_value; }
}; };
using scalar_type = HPR_SCALAR; using scalar_type = HPR_SCALAR;
using scalar = Scalar<HPR_SCALAR>; using scalar = Scalar<HPR_SCALAR>;
// template<> scalar::value_type scalar::s_precision = static_cast<scalar::value_type>(1e-15); // template<> scalar::value_type scalar::s_precision = static_cast<scalar::value_type>(1e-15);
/// scalar vs scalar /// scalar vs scalar
constexpr scalar operator+(const scalar& s) { return s; } constexpr scalar operator+(const scalar& s) { return s; }
constexpr scalar operator-(const scalar& s) { return -s.value(); } constexpr scalar operator-(const scalar& s) { return -s.value(); }
constexpr bool operator!(const scalar& s) { return !static_cast<bool>(s.value()); } constexpr bool operator!(const scalar& s) { return !static_cast<bool>(s.value()); }
constexpr scalar& operator+=(scalar& lhs, const scalar& rhs) { lhs.value() += static_cast<scalar::value_type>(rhs.value()); return lhs; } constexpr scalar& operator+=(scalar& lhs, const scalar& rhs) { lhs.value() += static_cast<scalar::value_type>(rhs.value()); return lhs; }
constexpr scalar& operator-=(scalar& lhs, const scalar& rhs) { lhs.value() -= static_cast<scalar::value_type>(rhs.value()); return lhs; } constexpr scalar& operator-=(scalar& lhs, const scalar& rhs) { lhs.value() -= static_cast<scalar::value_type>(rhs.value()); return lhs; }
constexpr scalar& operator*=(scalar& lhs, const scalar& rhs) { lhs.value() *= static_cast<scalar::value_type>(rhs.value()); return lhs; } constexpr scalar& operator*=(scalar& lhs, const scalar& rhs) { lhs.value() *= static_cast<scalar::value_type>(rhs.value()); return lhs; }
constexpr scalar& operator/=(scalar& lhs, const scalar& rhs) { lhs.value() /= static_cast<scalar::value_type>(rhs.value()); return lhs; } constexpr scalar& operator/=(scalar& lhs, const scalar& rhs) { lhs.value() /= static_cast<scalar::value_type>(rhs.value()); return lhs; }
constexpr scalar operator+(const scalar& lhs, const scalar& rhs) { return lhs.value() + rhs.value(); } constexpr scalar operator+(const scalar& lhs, const scalar& rhs) { return lhs.value() + rhs.value(); }
constexpr scalar operator-(const scalar& lhs, const scalar& rhs) { return lhs.value() - rhs.value(); } constexpr scalar operator-(const scalar& lhs, const scalar& rhs) { return lhs.value() - rhs.value(); }
constexpr scalar operator*(const scalar& lhs, const scalar& rhs) { return lhs.value() * rhs.value(); } constexpr scalar operator*(const scalar& lhs, const scalar& rhs) { return lhs.value() * rhs.value(); }
constexpr scalar operator/(const scalar& lhs, const scalar& rhs) { return lhs.value() / rhs.value(); } constexpr scalar operator/(const scalar& lhs, const scalar& rhs) { return lhs.value() / rhs.value(); }
constexpr bool operator==(const scalar& lhs, const scalar& rhs) { return lhs.value() == rhs.value(); } constexpr bool operator==(const scalar& lhs, const scalar& rhs) { return lhs.value() == rhs.value(); }
constexpr bool operator!=(const scalar& lhs, const scalar& rhs) { return lhs.value() != rhs.value(); } constexpr bool operator!=(const scalar& lhs, const scalar& rhs) { return lhs.value() != rhs.value(); }
constexpr bool operator&&(const scalar& lhs, const scalar& rhs) { return static_cast<bool>(lhs) && static_cast<bool>(rhs); } constexpr bool operator&&(const scalar& lhs, const scalar& rhs) { return static_cast<bool>(lhs) && static_cast<bool>(rhs); }
constexpr bool operator||(const scalar& lhs, const scalar& rhs) { return static_cast<bool>(lhs) || static_cast<bool>(rhs); } constexpr bool operator||(const scalar& lhs, const scalar& rhs) { return static_cast<bool>(lhs) || static_cast<bool>(rhs); }
constexpr bool operator>(const scalar& lhs, const scalar& rhs) { return lhs.value() > rhs.value(); } constexpr bool operator>(const scalar& lhs, const scalar& rhs) { return lhs.value() > rhs.value(); }
constexpr bool operator<(const scalar& lhs, const scalar& rhs) { return lhs.value() < rhs.value(); } constexpr bool operator<(const scalar& lhs, const scalar& rhs) { return lhs.value() < rhs.value(); }
constexpr bool operator>=(const scalar& lhs, const scalar& rhs) { return lhs.value() >= rhs.value(); } constexpr bool operator>=(const scalar& lhs, const scalar& rhs) { return lhs.value() >= rhs.value(); }
constexpr bool operator<=(const scalar& lhs, const scalar& rhs) { return lhs.value() <= rhs.value(); } constexpr bool operator<=(const scalar& lhs, const scalar& rhs) { return lhs.value() <= rhs.value(); }
// std::ostream& operator<<(std::ostream& stream, const scalar& s) { return stream << s.value(); } // std::ostream& operator<<(std::ostream& stream, const scalar& s) { return stream << s.value(); }
/// scalar vs Scalar<T> /// scalar vs Scalar<T>
template <IsScalar T> constexpr scalar& operator+=(scalar& lhs, const Scalar<T>& rhs) { lhs.value() += static_cast<scalar::value_type>(rhs.value()); return lhs; } template <IsScalar T> constexpr scalar& operator+=(scalar& lhs, const Scalar<T>& rhs) { lhs.value() += static_cast<scalar::value_type>(rhs.value()); return lhs; }
template <IsScalar T> constexpr scalar& operator-=(scalar& lhs, const Scalar<T>& rhs) { lhs.value() -= static_cast<scalar::value_type>(rhs.value()); return lhs; } template <IsScalar T> constexpr scalar& operator-=(scalar& lhs, const Scalar<T>& rhs) { lhs.value() -= static_cast<scalar::value_type>(rhs.value()); return lhs; }
template <IsScalar T> constexpr scalar& operator*=(scalar& lhs, const Scalar<T>& rhs) { lhs.value() *= static_cast<scalar::value_type>(rhs.value()); return lhs; } template <IsScalar T> constexpr scalar& operator*=(scalar& lhs, const Scalar<T>& rhs) { lhs.value() *= static_cast<scalar::value_type>(rhs.value()); return lhs; }
template <IsScalar T> constexpr scalar& operator/=(scalar& lhs, const Scalar<T>& rhs) { lhs.value() /= static_cast<scalar::value_type>(rhs.value()); return lhs; } template <IsScalar T> constexpr scalar& operator/=(scalar& lhs, const Scalar<T>& rhs) { lhs.value() /= static_cast<scalar::value_type>(rhs.value()); return lhs; }
template <IsScalar T> constexpr scalar operator+(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() + static_cast<scalar::value_type>(rhs.value()); } template <IsScalar T> constexpr scalar operator+(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() + static_cast<scalar::value_type>(rhs.value()); }
template <IsScalar T> constexpr scalar operator+(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) + rhs.value(); } template <IsScalar T> constexpr scalar operator+(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) + rhs.value(); }
template <IsScalar T> constexpr scalar operator-(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() - static_cast<scalar::value_type>(rhs.value()); } template <IsScalar T> constexpr scalar operator-(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() - static_cast<scalar::value_type>(rhs.value()); }
template <IsScalar T> constexpr scalar operator-(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) - rhs.value(); } template <IsScalar T> constexpr scalar operator-(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) - rhs.value(); }
template <IsScalar T> constexpr scalar operator*(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() * static_cast<scalar::value_type>(rhs.value()); } template <IsScalar T> constexpr scalar operator*(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() * static_cast<scalar::value_type>(rhs.value()); }
template <IsScalar T> constexpr scalar operator*(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) * rhs.value(); } template <IsScalar T> constexpr scalar operator*(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) * rhs.value(); }
template <IsScalar T> constexpr scalar operator/(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() / static_cast<scalar::value_type>(rhs.value()); } template <IsScalar T> constexpr scalar operator/(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() / static_cast<scalar::value_type>(rhs.value()); }
template <IsScalar T> constexpr scalar operator/(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) / rhs.value(); } template <IsScalar T> constexpr scalar operator/(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) / rhs.value(); }
template <IsScalar T> constexpr bool operator==(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() == static_cast<scalar::value_type>(rhs.value()); } template <IsScalar T> constexpr bool operator==(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() == static_cast<scalar::value_type>(rhs.value()); }
template <IsScalar T> constexpr bool operator==(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) == rhs.value(); } template <IsScalar T> constexpr bool operator==(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) == rhs.value(); }
template <IsScalar T> constexpr bool operator!=(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() != static_cast<scalar::value_type>(rhs.value()); } template <IsScalar T> constexpr bool operator!=(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() != static_cast<scalar::value_type>(rhs.value()); }
template <IsScalar T> constexpr bool operator!=(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) != rhs.value(); } template <IsScalar T> constexpr bool operator!=(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) != rhs.value(); }
template <IsScalar T> constexpr bool operator&&(const scalar& lhs, const Scalar<T>& rhs) { return static_cast<bool>(lhs) && static_cast<bool>(rhs); } template <IsScalar T> constexpr bool operator&&(const scalar& lhs, const Scalar<T>& rhs) { return static_cast<bool>(lhs) && static_cast<bool>(rhs); }
template <IsScalar T> constexpr bool operator&&(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<bool>(lhs) && static_cast<bool>(rhs); } template <IsScalar T> constexpr bool operator&&(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<bool>(lhs) && static_cast<bool>(rhs); }
template <IsScalar T> constexpr bool operator||(const scalar& lhs, const Scalar<T>& rhs) { return static_cast<bool>(lhs) || static_cast<bool>(rhs); } template <IsScalar T> constexpr bool operator||(const scalar& lhs, const Scalar<T>& rhs) { return static_cast<bool>(lhs) || static_cast<bool>(rhs); }
template <IsScalar T> constexpr bool operator||(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<bool>(lhs) || static_cast<bool>(rhs); } template <IsScalar T> constexpr bool operator||(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<bool>(lhs) || static_cast<bool>(rhs); }
template <IsScalar T> constexpr bool operator>(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() > static_cast<scalar::value_type>(rhs.value()); } template <IsScalar T> constexpr bool operator>(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() > static_cast<scalar::value_type>(rhs.value()); }
template <IsScalar T> constexpr bool operator>(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) > rhs.value(); } template <IsScalar T> constexpr bool operator>(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) > rhs.value(); }
template <IsScalar T> constexpr bool operator<(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() < static_cast<scalar::value_type>(rhs.value()); } template <IsScalar T> constexpr bool operator<(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() < static_cast<scalar::value_type>(rhs.value()); }
template <IsScalar T> constexpr bool operator<(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) < rhs.value(); } template <IsScalar T> constexpr bool operator<(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) < rhs.value(); }
template <IsScalar T> constexpr bool operator>=(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() >= static_cast<scalar::value_type>(rhs.value()); } template <IsScalar T> constexpr bool operator>=(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() >= static_cast<scalar::value_type>(rhs.value()); }
template <IsScalar T> constexpr bool operator>=(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) >= rhs.value(); } template <IsScalar T> constexpr bool operator>=(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) >= rhs.value(); }
template <IsScalar T> constexpr bool operator<=(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() <= static_cast<scalar::value_type>(rhs.value()); } template <IsScalar T> constexpr bool operator<=(const scalar& lhs, const Scalar<T>& rhs) { return lhs.value() <= static_cast<scalar::value_type>(rhs.value()); }
template <IsScalar T> constexpr bool operator<=(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) <= rhs.value(); } template <IsScalar T> constexpr bool operator<=(const Scalar<T>& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs.value()) <= rhs.value(); }
template <IsScalar T> std::ostream& operator<<(std::ostream& stream, const Scalar<T>& s) { return stream << s.value(); } template <IsScalar T> std::ostream& operator<<(std::ostream& stream, const Scalar<T>& s) { return stream << s.value(); }
template <IsScalar T> std::istream& operator>>(std::istream& stream, Scalar<T>& s) { return stream >> s.value(); } template <IsScalar T> std::istream& operator>>(std::istream& stream, Scalar<T>& s) { return stream >> s.value(); }
/// scalar vs real /// scalar vs real
template <IsReal T> constexpr scalar& operator+=(scalar& lhs, const T& rhs) { lhs.value() += static_cast<scalar::value_type>(rhs); return lhs; } template <IsReal T> constexpr scalar& operator+=(scalar& lhs, const T& rhs) { lhs.value() += static_cast<scalar::value_type>(rhs); return lhs; }
template <IsReal T> constexpr scalar& operator-=(scalar& lhs, const T& rhs) { lhs.value() -= static_cast<scalar::value_type>(rhs); return lhs; } template <IsReal T> constexpr scalar& operator-=(scalar& lhs, const T& rhs) { lhs.value() -= static_cast<scalar::value_type>(rhs); return lhs; }
template <IsReal T> constexpr scalar& operator*=(scalar& lhs, const T& rhs) { lhs.value() *= static_cast<scalar::value_type>(rhs); return lhs; } template <IsReal T> constexpr scalar& operator*=(scalar& lhs, const T& rhs) { lhs.value() *= static_cast<scalar::value_type>(rhs); return lhs; }
template <IsReal T> constexpr scalar& operator/=(scalar& lhs, const T& rhs) { lhs.value() /= static_cast<scalar::value_type>(rhs); return lhs; } template <IsReal T> constexpr scalar& operator/=(scalar& lhs, const T& rhs) { lhs.value() /= static_cast<scalar::value_type>(rhs); return lhs; }
template <IsReal T> constexpr T& operator+=(T& lhs, const scalar& rhs) { lhs += static_cast<T>(rhs); return lhs; } template <IsReal T> constexpr T& operator+=(T& lhs, const scalar& rhs) { lhs += static_cast<T>(rhs); return lhs; }
template <IsReal T> constexpr T& operator-=(T& lhs, const scalar& rhs) { lhs -= static_cast<T>(rhs); return lhs; } template <IsReal T> constexpr T& operator-=(T& lhs, const scalar& rhs) { lhs -= static_cast<T>(rhs); return lhs; }
template <IsReal T> constexpr T& operator*=(T& lhs, const scalar& rhs) { lhs *= static_cast<T>(rhs); return lhs; } template <IsReal T> constexpr T& operator*=(T& lhs, const scalar& rhs) { lhs *= static_cast<T>(rhs); return lhs; }
template <IsReal T> constexpr T& operator/=(T& lhs, const scalar& rhs) { lhs /= static_cast<T>(rhs); return lhs; } template <IsReal T> constexpr T& operator/=(T& lhs, const scalar& rhs) { lhs /= static_cast<T>(rhs); return lhs; }
template <IsReal T> constexpr scalar operator+(const scalar& lhs, const T& rhs) { return lhs.value() + static_cast<scalar::value_type>(rhs); } template <IsReal T> constexpr scalar operator+(const scalar& lhs, const T& rhs) { return lhs.value() + static_cast<scalar::value_type>(rhs); }
template <IsReal T> constexpr scalar operator+(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) + rhs.value(); } template <IsReal T> constexpr scalar operator+(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) + rhs.value(); }
template <IsReal T> constexpr scalar operator-(const scalar& lhs, const T& rhs) { return lhs.value() - static_cast<scalar::value_type>(rhs); } template <IsReal T> constexpr scalar operator-(const scalar& lhs, const T& rhs) { return lhs.value() - static_cast<scalar::value_type>(rhs); }
template <IsReal T> constexpr scalar operator-(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) - rhs.value(); } template <IsReal T> constexpr scalar operator-(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) - rhs.value(); }
template <IsReal T> constexpr scalar operator*(const scalar& lhs, const T& rhs) { return lhs.value() * static_cast<scalar::value_type>(rhs); } template <IsReal T> constexpr scalar operator*(const scalar& lhs, const T& rhs) { return lhs.value() * static_cast<scalar::value_type>(rhs); }
template <IsReal T> constexpr scalar operator*(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) * rhs.value(); } template <IsReal T> constexpr scalar operator*(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) * rhs.value(); }
template <IsReal T> constexpr scalar operator/(const scalar& lhs, const T& rhs) { return lhs.value() / static_cast<scalar::value_type>(rhs); } template <IsReal T> constexpr scalar operator/(const scalar& lhs, const T& rhs) { return lhs.value() / static_cast<scalar::value_type>(rhs); }
template <IsReal T> constexpr scalar operator/(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) / rhs.value(); } template <IsReal T> constexpr scalar operator/(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) / rhs.value(); }
template <IsReal T> constexpr bool operator==(const scalar& lhs, const T& rhs) { return lhs.value() == static_cast<scalar::value_type>(rhs); } template <IsReal T> constexpr bool operator==(const scalar& lhs, const T& rhs) { return lhs.value() == static_cast<scalar::value_type>(rhs); }
template <IsReal T> constexpr bool operator==(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) == rhs.value(); } template <IsReal T> constexpr bool operator==(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) == rhs.value(); }
template <IsReal T> constexpr bool operator!=(const scalar& lhs, const T& rhs) { return lhs.value() != static_cast<scalar::value_type>(rhs); } template <IsReal T> constexpr bool operator!=(const scalar& lhs, const T& rhs) { return lhs.value() != static_cast<scalar::value_type>(rhs); }
template <IsReal T> constexpr bool operator!=(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) != rhs.value(); } template <IsReal T> constexpr bool operator!=(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) != rhs.value(); }
template <IsReal T> constexpr bool operator&&(const scalar& lhs, const T& rhs) { return static_cast<bool>(lhs) && static_cast<bool>(rhs); } template <IsReal T> constexpr bool operator&&(const scalar& lhs, const T& rhs) { return static_cast<bool>(lhs) && static_cast<bool>(rhs); }
template <IsReal T> constexpr bool operator&&(const T& lhs, const scalar& rhs) { return static_cast<bool>(lhs) && static_cast<bool>(rhs); } template <IsReal T> constexpr bool operator&&(const T& lhs, const scalar& rhs) { return static_cast<bool>(lhs) && static_cast<bool>(rhs); }
template <IsReal T> constexpr bool operator||(const scalar& lhs, const T& rhs) { return static_cast<bool>(lhs) || static_cast<bool>(rhs); } template <IsReal T> constexpr bool operator||(const scalar& lhs, const T& rhs) { return static_cast<bool>(lhs) || static_cast<bool>(rhs); }
template <IsReal T> constexpr bool operator||(const T& lhs, const scalar& rhs) { return static_cast<bool>(lhs) || static_cast<bool>(rhs); } template <IsReal T> constexpr bool operator||(const T& lhs, const scalar& rhs) { return static_cast<bool>(lhs) || static_cast<bool>(rhs); }
template <IsReal T> constexpr bool operator>(const scalar& lhs, const T& rhs) { return lhs.value() > static_cast<scalar::value_type>(rhs); } template <IsReal T> constexpr bool operator>(const scalar& lhs, const T& rhs) { return lhs.value() > static_cast<scalar::value_type>(rhs); }
template <IsReal T> constexpr bool operator>(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) > rhs.value(); } template <IsReal T> constexpr bool operator>(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) > rhs.value(); }
template <IsReal T> constexpr bool operator<(const scalar& lhs, const T& rhs) { return lhs.value() < static_cast<scalar::value_type>(rhs); } template <IsReal T> constexpr bool operator<(const scalar& lhs, const T& rhs) { return lhs.value() < static_cast<scalar::value_type>(rhs); }
template <IsReal T> constexpr bool operator<(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) < rhs.value(); } template <IsReal T> constexpr bool operator<(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) < rhs.value(); }
template <IsReal T> constexpr bool operator>=(const scalar& lhs, const T& rhs) { return lhs.value() >= static_cast<scalar::value_type>(rhs); } template <IsReal T> constexpr bool operator>=(const scalar& lhs, const T& rhs) { return lhs.value() >= static_cast<scalar::value_type>(rhs); }
template <IsReal T> constexpr bool operator>=(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) >= rhs.value(); } template <IsReal T> constexpr bool operator>=(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) >= rhs.value(); }
template <IsReal T> constexpr bool operator<=(const scalar& lhs, const T& rhs) { return lhs.value() <= static_cast<scalar::value_type>(rhs); } template <IsReal T> constexpr bool operator<=(const scalar& lhs, const T& rhs) { return lhs.value() <= static_cast<scalar::value_type>(rhs); }
template <IsReal T> constexpr bool operator<=(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) <= rhs.value(); } template <IsReal T> constexpr bool operator<=(const T& lhs, const scalar& rhs) { return static_cast<scalar::value_type>(lhs) <= rhs.value(); }
#else #else
using scalar_type = HPR_SCALAR; using scalar_type = HPR_SCALAR;
using scalar = HPR_SCALAR; using scalar = HPR_SCALAR;
#endif #endif
// constants // constants
HPR_CONSTEXPR scalar pi() { return std::numbers::pi_v<scalar_type>; } HPR_CONSTEXPR scalar pi() { return std::numbers::pi_v<scalar_type>; }
HPR_CONSTEXPR scalar e() { return std::numbers::e_v<scalar_type>; } HPR_CONSTEXPR scalar e() { return std::numbers::e_v<scalar_type>; }
// transcendentals // transcendentals
template <IsReal T> HPR_CONSTEXPR scalar cos(const T& s) { return std::cos(static_cast<scalar_type>(s));} template <IsReal T> HPR_CONSTEXPR scalar cos(const T& s) { return std::cos(static_cast<scalar_type>(s));}
template <IsReal T> HPR_CONSTEXPR scalar acos(const T& s) { return std::acos(static_cast<scalar_type>(s)); } template <IsReal T> HPR_CONSTEXPR scalar acos(const T& s) { return std::acos(static_cast<scalar_type>(s)); }
template <IsReal T> HPR_CONSTEXPR scalar cosh(const T& s) { return std::cosh(static_cast<scalar_type>(s)); } template <IsReal T> HPR_CONSTEXPR scalar cosh(const T& s) { return std::cosh(static_cast<scalar_type>(s)); }
template <IsReal T> HPR_CONSTEXPR scalar acosh(const T& s) { return std::acosh(static_cast<scalar_type>(s)); } template <IsReal T> HPR_CONSTEXPR scalar acosh(const T& s) { return std::acosh(static_cast<scalar_type>(s)); }
template <IsReal T> HPR_CONSTEXPR scalar sin(const T& s) { return std::sin(static_cast<scalar_type>(s)); } template <IsReal T> HPR_CONSTEXPR scalar sin(const T& s) { return std::sin(static_cast<scalar_type>(s)); }
template <IsReal T> HPR_CONSTEXPR scalar asin(const T& s) { return std::asin(static_cast<scalar_type>(s)); } template <IsReal T> HPR_CONSTEXPR scalar asin(const T& s) { return std::asin(static_cast<scalar_type>(s)); }
template <IsReal T> HPR_CONSTEXPR scalar sinh(const T& s) { return std::sinh(static_cast<scalar_type>(s)); } template <IsReal T> HPR_CONSTEXPR scalar sinh(const T& s) { return std::sinh(static_cast<scalar_type>(s)); }
template <IsReal T> HPR_CONSTEXPR scalar asinh(const T& s) { return std::asinh(static_cast<scalar_type>(s)); } template <IsReal T> HPR_CONSTEXPR scalar asinh(const T& s) { return std::asinh(static_cast<scalar_type>(s)); }
template <IsReal T> HPR_CONSTEXPR scalar tan(const T& s) { return std::tan(static_cast<scalar_type>(s)); } template <IsReal T> HPR_CONSTEXPR scalar tan(const T& s) { return std::tan(static_cast<scalar_type>(s)); }
template <IsReal T> HPR_CONSTEXPR scalar atan(const T& s) { return std::atan(static_cast<scalar_type>(s)); } template <IsReal T> HPR_CONSTEXPR scalar atan(const T& s) { return std::atan(static_cast<scalar_type>(s)); }
template <IsReal T, IsReal X> HPR_CONSTEXPR scalar atan2(const T& s, const X& s2) { return std::atan2(static_cast<scalar_type>(s), static_cast<scalar_type>(s2)); } template <IsReal T, IsReal X> HPR_CONSTEXPR scalar atan2(const T& s, const X& s2) { return std::atan2(static_cast<scalar_type>(s), static_cast<scalar_type>(s2)); }
template <IsReal T> HPR_CONSTEXPR scalar tanh(const T& s) { return std::tanh(static_cast<scalar_type>(s)); } template <IsReal T> HPR_CONSTEXPR scalar tanh(const T& s) { return std::tanh(static_cast<scalar_type>(s)); }
template <IsReal T> HPR_CONSTEXPR scalar atanh(const T& s) { return std::atanh(static_cast<scalar_type>(s)); } template <IsReal T> HPR_CONSTEXPR scalar atanh(const T& s) { return std::atanh(static_cast<scalar_type>(s)); }
template <IsReal T> HPR_CONSTEXPR scalar exp(const T& s) { return std::exp(static_cast<scalar_type>(s)); } template <IsReal T> HPR_CONSTEXPR scalar exp(const T& s) { return std::exp(static_cast<scalar_type>(s)); }
template <IsReal T> HPR_CONSTEXPR scalar log(const T& s) { return std::log(static_cast<scalar_type>(s)); } template <IsReal T> HPR_CONSTEXPR scalar log(const T& s) { return std::log(static_cast<scalar_type>(s)); }
template <IsReal T> HPR_CONSTEXPR scalar log10(const T& s) { return std::log10(static_cast<scalar_type>(s)); } template <IsReal T> HPR_CONSTEXPR scalar log10(const T& s) { return std::log10(static_cast<scalar_type>(s)); }
template <IsReal T, IsReal X> HPR_CONSTEXPR scalar pow(const T& s, const X& d) { return std::pow(static_cast<scalar_type>(s), static_cast<scalar_type>(d)); } template <IsReal T, IsReal X> HPR_CONSTEXPR scalar pow(const T& s, const X& d) { return std::pow(static_cast<scalar_type>(s), static_cast<scalar_type>(d)); }
template <IsReal T> HPR_CONSTEXPR scalar sqrt(const T& s) { return std::sqrt(static_cast<scalar_type>(s)); } template <IsReal T> HPR_CONSTEXPR scalar sqrt(const T& s) { return std::sqrt(static_cast<scalar_type>(s)); }
template <IsReal T> HPR_CONSTEXPR scalar isqrt(const T& s) { return static_cast<T>(1) / sqrt(static_cast<scalar_type>(s)); } template <IsReal T> HPR_CONSTEXPR scalar isqrt(const T& s) { return static_cast<T>(1) / sqrt(static_cast<scalar_type>(s)); }
// //
static scalar_type scalar_precision = static_cast<scalar_type>(1e-15); static scalar_type scalar_precision = static_cast<scalar_type>(1e-15);
inline scalar_type precision() inline scalar_type precision()
{ {
return scalar_precision; return scalar_precision;
} }
template <IsReal T> inline void precision(const T& precision) template <IsReal T> inline void precision(const T& precision)
{ {
scalar_precision = static_cast<scalar_type>(precision); scalar_precision = static_cast<scalar_type>(precision);
} }
HPR_CONSTEXPR scalar inf() { return std::numeric_limits<scalar_type>::infinity(); } HPR_CONSTEXPR scalar inf() { return std::numeric_limits<scalar_type>::infinity(); }
HPR_CONSTEXPR scalar epsilon() { return std::numeric_limits<scalar_type>::epsilon(); } HPR_CONSTEXPR scalar epsilon() { return std::numeric_limits<scalar_type>::epsilon(); }
HPR_CONSTEXPR scalar isnan(const scalar& s) { return std::isnan(static_cast<scalar_type>(s)); } HPR_CONSTEXPR scalar isnan(const scalar& s) { return std::isnan(static_cast<scalar_type>(s)); }
HPR_CONSTEXPR scalar abs(const scalar& s) { return std::abs(static_cast<scalar_type>(s)); } HPR_CONSTEXPR scalar abs(const scalar& s) { return std::abs(static_cast<scalar_type>(s)); }
HPR_CONSTEXPR scalar mag(const scalar& s) { return std::abs(static_cast<scalar_type>(s)); } HPR_CONSTEXPR scalar mag(const scalar& s) { return std::abs(static_cast<scalar_type>(s)); }
HPR_CONSTEXPR bool equal(const scalar& lhs, const scalar& rhs, const scalar& precision = hpr::precision()) { return abs(lhs - rhs) < precision; } HPR_CONSTEXPR bool equal(const scalar& lhs, const scalar& rhs, const scalar& precision = hpr::precision()) { return abs(lhs - rhs) < precision; }
//! Convert degrees to radians //! Convert degrees to radians
HPR_CONSTEXPR scalar rad(const scalar& s) { return s * pi() / static_cast<scalar_type>(180); } HPR_CONSTEXPR scalar rad(const scalar& s) { return s * pi() / static_cast<scalar_type>(180); }
//! Convert radians to degrees //! Convert radians to degrees
HPR_CONSTEXPR scalar deg(const scalar& s) { return s * static_cast<scalar_type>(180) / pi(); } HPR_CONSTEXPR scalar deg(const scalar& s) { return s * static_cast<scalar_type>(180) / pi(); }
HPR_CONSTEXPR scalar min(const scalar& s1, const scalar& s2) { return std::min(static_cast<scalar_type>(s1), static_cast<scalar_type>(s2));} HPR_CONSTEXPR scalar min(const scalar& s1, const scalar& s2) { return std::min(static_cast<scalar_type>(s1), static_cast<scalar_type>(s2));}
HPR_CONSTEXPR scalar max(const scalar& s1, const scalar& s2) { return std::max(static_cast<scalar_type>(s1), static_cast<scalar_type>(s2)); } HPR_CONSTEXPR scalar max(const scalar& s1, const scalar& s2) { return std::max(static_cast<scalar_type>(s1), static_cast<scalar_type>(s2)); }
HPR_CONSTEXPR scalar clip(const scalar& s, const scalar& sMin, const scalar& sMax) { return min(sMax, max(s, sMin)); } HPR_CONSTEXPR scalar clip(const scalar& s, const scalar& sMin, const scalar& sMax) { return min(sMax, max(s, sMin)); }
} // end namespace hpr } // end namespace hpr
#ifdef HPR_SCALAR_IMPLEMENTATION #ifdef HPR_SCALAR_IMPLEMENTATION
namespace std namespace std
{ {
template <class T> struct is_floating_point<hpr::scalar> : true_type {}; template <class T> struct is_floating_point<hpr::scalar> : true_type {};
} // end namespace std } // end namespace std
#endif #endif

3
source/hpr/shape.hpp Normal file
View File

@ -0,0 +1,3 @@
#pragma once
#include <hpr/shape/shape.hpp>

360
source/hpr/shape/shape.hpp Normal file
View File

@ -0,0 +1,360 @@
#pragma once
#include <hpr/numeric.hpp>
#include <hpr/container/dynamic_array.hpp>
#include <map>
#include <string>
#include <Geom_Surface.hxx>
#include <GeomLProp_SLProps.hxx>
#include <Poly_Triangle.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Wire.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Compound.hxx>
#include <TopoDS_CompSolid.hxx>
#include <TopoDS_Shell.hxx>
#include <TopoDS_Solid.hxx>
#include <TopExp_Explorer.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_MakeShell.hxx>
#include <BRepBuilderAPI_MakeSolid.hxx>
#include <BRepBuilderAPI_Sewing.hxx>
#include <BRep_Builder.hxx>
#include <BRepBndLib.hxx>
#include <BRep_Tool.hxx>
#include <BRepTools.hxx>
#include <BRepGProp.hxx>
#include <GProp_GProps.hxx>
#include <ShapeUpgrade_UnifySameDomain.hxx>
#include <BRepExtrema_DistShapeShape.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <BRepBuilderAPI_GTransform.hxx>
#include <BRepFilletAPI_MakeFillet.hxx>
#include <BRepAlgoAPI_Fuse.hxx>
#include <BRepAlgoAPI_Common.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepPrimAPI_MakeSphere.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <BRepPrimAPI_MakePrism.hxx>
#include <STEPControl_Writer.hxx>
#include <Interface_Static.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <Poly_PolygonOnTriangulation.hxx>
#include <Poly_Triangulation.hxx>
#include <TopAbs_ShapeEnum.hxx>
#include <TopLoc_Location.hxx>
#include <NCollection_List.hxx>
#include <ShapeFix_Solid.hxx>
#include <ShapeFix_Shell.hxx>
#include <ShapeFix_Face.hxx>
namespace hpr::csg
{
class Shape;
}
namespace std
{
template<>
struct less<hpr::csg::Shape>
{
bool operator() (const hpr::csg::Shape& s1, const hpr::csg::Shape& s2) const;
};
}
namespace hpr::csg
{
// Class declaration
class Shape
{
public:
enum class Type
{
Compound,
Compsolid,
Solid,
Shell,
Face,
Wire,
Edge,
Vertex,
Shape,
Unknown
};
enum class Format
{
Unknown,
STEP
};
class Metadata
{
public:
std::string label;
public:
Metadata() :
label {"default"}
{}
void merge(const Metadata& data)
{
if (label == "default" && data.label != "default")
label = data.label;
}
};
public:
// TODO: clean up map
static
std::map<Shape, Shape::Metadata> metadata;
protected:
TopoDS_Shape p_shape;
public:
[[nodiscard]]
TopoDS_Shape tshape() const { return p_shape; }
Shape(const TopoDS_Shape& s) :
p_shape {s}
{}
Shape(TopoDS_Shape&& s) noexcept:
p_shape {std::forward<TopoDS_Shape>(s)}
{}
public:
Shape() :
p_shape {}
{}
virtual
~Shape() = default;
//{
//if (metadata.contains(*this))
// metadata.erase(*this);
//}
[[nodiscard]]
Type type() const
{
switch (p_shape.ShapeType())
{
case TopAbs_VERTEX:
return Type::Vertex;
case TopAbs_EDGE:
return Type::Edge;
case TopAbs_FACE:
return Type::Face;
case TopAbs_WIRE:
return Type::Wire;
case TopAbs_SHELL:
return Type::Shell;
case TopAbs_SOLID:
return Type::Solid;
case TopAbs_COMPOUND:
return Type::Compound;
case TopAbs_COMPSOLID:
return Type::Compsolid;
case TopAbs_SHAPE:
return Type::Shape;
default:
return Type::Unknown;
}
}
[[nodiscard]]
vec3 center() const
{
GProp_GProps props;
switch (type())
{
case Type::Solid:
case Type::Compsolid:
case Type::Compound:
BRepGProp::VolumeProperties(p_shape, props);
case Type::Shell:
case Type::Face:
BRepGProp::SurfaceProperties(p_shape, props);
default:
BRepGProp::LinearProperties(p_shape, props);
}
gp_Pnt center {props.CentreOfMass()};
return vec3 {static_cast<scalar>(center.X()), static_cast<scalar>(center.Y()), static_cast<scalar>(center.Z())};
}
[[nodiscard]]
double length() const
{
GProp_GProps props;
switch (type())
{
case Type::Vertex:
return 0;
default:
BRepGProp::LinearProperties(p_shape, props);
return props.Mass();
}
}
[[nodiscard]]
double area() const
{
GProp_GProps props;
switch (type())
{
case Type::Vertex:
case Type::Edge:
case Type::Wire:
return 0;
default:
BRepGProp::SurfaceProperties(p_shape, props);
return props.Mass();
}
}
[[nodiscard]]
double volume() const
{
GProp_GProps props;
switch (type())
{
case Type::Compsolid:
case Type::Solid:
BRepGProp::VolumeProperties(p_shape, props);
return props.Mass();
default:
return 0;
}
}
void label(const std::string& label) const
{
metadata[*this].label = label;
}
[[nodiscard]]
std::string label() const
{
return metadata[*this].label;
}
void dump(const std::string& filename, Format format) const
{
if (p_shape.IsNull())
throw std::runtime_error("Trying to export null shape");
switch (format)
{
case Format::STEP:
{
STEPControl_Writer writer;
Interface_Static::SetCVal("xstep.cascade.unit", "MM");
Interface_Static::SetCVal("write.step.unit", "MM");
Interface_Static::SetIVal("write.step.nonmanifold", 1);
writer.Transfer(p_shape, STEPControl_AsIs);
writer.Write(filename.c_str());
break;
}
case Format::Unknown:
default:
throw std::invalid_argument("Unknown export format");
}
}
//
[[nodiscard]]
sarray<vec3, 2> boundingBox() const
{
Bnd_Box bbox;
BRepBndLib::Add(p_shape, bbox, true);
gp_Pnt p1 {bbox.CornerMin()};
gp_Pnt p2 {bbox.CornerMax()};
return sarray<vec3, 2> {
{static_cast<scalar>(p1.X()), static_cast<scalar>(p1.Y()), static_cast<scalar>(p1.Z())},
{static_cast<scalar>(p2.X()), static_cast<scalar>(p2.Y()), static_cast<scalar>(p2.Z())}
};
}
void incrementalMesh(double deflection)
{
BRepTools::Clean(p_shape);
BRepMesh_IncrementalMesh(p_shape, deflection, true);
}
darray<Shape> subShapes(Type type) const
{
darray<Shape> shapes;
for (TopExp_Explorer exp(p_shape, static_cast<TopAbs_ShapeEnum>(type)); exp.More(); exp.Next())
shapes.push(Shape(exp.Current()));
return shapes;
}
darray<Shape> edges() const
{
return subShapes(Type::Edge);
}
darray<Shape> faces() const
{
return subShapes(Type::Face);
}
darray<Shape> shells() const
{
return subShapes(Type::Shell);
}
};
double distance(const Shape& lhs, const Shape& rhs)
{
return BRepExtrema_DistShapeShape(lhs.tshape(), rhs.tshape()).Value();
}
}

View File

@ -0,0 +1,5 @@

View File

@ -1,7 +1,7 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
testing::InitGoogleTest(&argc, argv); testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
} }

View File

@ -1,94 +1,94 @@
#pragma once #pragma once
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <hpr/container/static_array.hpp> #include <hpr/container/static_array.hpp>
#include <hpr/container/dynamic_array.hpp> #include <hpr/container/dynamic_array.hpp>
#include <hpr/container/tree_node.hpp> #include <hpr/container/tree_node.hpp>
TEST(containers, StaticArray) TEST(containers, StaticArray)
{ {
hpr::StaticArray<float, 3> arr {7, 3, 2}; hpr::StaticArray<float, 3> arr {7, 3, 2};
hpr::StaticArray<float, 4> sarr {arr, 5}; hpr::StaticArray<float, 4> sarr {arr, 5};
hpr::StaticArray<float, 4> sarr2 {7, 3, 2, 5}; hpr::StaticArray<float, 4> sarr2 {7, 3, 2, 5};
//hpr::StaticArray<float, 0> sarr4; //hpr::StaticArray<float, 0> sarr4;
EXPECT_EQ(sarr, sarr2); EXPECT_EQ(sarr, sarr2);
//EXPECT_EQ(sarr4.data(), nullptr); //EXPECT_EQ(sarr4.data(), nullptr);
//EXPECT_EQ(sarr4.is_empty(), true); //EXPECT_EQ(sarr4.is_empty(), true);
EXPECT_EQ(sarr.size(), 4); EXPECT_EQ(sarr.size(), 4);
EXPECT_EQ(sarr2.size(), 4); EXPECT_EQ(sarr2.size(), 4);
EXPECT_EQ(sarr[0], 7); EXPECT_EQ(sarr[0], 7);
EXPECT_EQ(sarr[1], 3); EXPECT_EQ(sarr[1], 3);
EXPECT_EQ(sarr[2], 2); EXPECT_EQ(sarr[2], 2);
EXPECT_EQ(sarr[3], 5); EXPECT_EQ(sarr[3], 5);
} }
TEST(containers, DynamicArray) TEST(containers, DynamicArray)
{ {
hpr::DynamicArray<float> arr {1, 3, 2}; hpr::DynamicArray<float> arr {1, 3, 2};
hpr::DynamicArray<float> arr2 {1, 3, 2}; hpr::DynamicArray<float> arr2 {1, 3, 2};
EXPECT_EQ(arr, arr2); EXPECT_EQ(arr, arr2);
EXPECT_TRUE(arr == arr2); EXPECT_TRUE(arr == arr2);
arr.remove(1); arr.remove(1);
EXPECT_EQ(arr, hpr::darray<float>({1, 2})); EXPECT_EQ(arr, hpr::darray<float>({1, 2}));
auto iter = arr2.begin(); auto iter = arr2.begin();
++iter; ++iter;
arr2.remove(iter); arr2.remove(iter);
EXPECT_EQ(arr2, hpr::darray<float>({1, 2})); EXPECT_EQ(arr2, hpr::darray<float>({1, 2}));
hpr::DynamicArray<float> arr3 {1, 3, 0, 2, 9, 0, 5}; hpr::DynamicArray<float> arr3 {1, 3, 0, 2, 9, 0, 5};
arr3.remove([](float num) { return num == 0; }); arr3.remove([](float num) { return num == 0; });
EXPECT_EQ(arr3, hpr::darray<float>({1, 3, 2, 9, 5})); EXPECT_EQ(arr3, hpr::darray<float>({1, 3, 2, 9, 5}));
EXPECT_EQ(arr3.size(), 5); EXPECT_EQ(arr3.size(), 5);
arr3.insert(3, 19); arr3.insert(3, 19);
EXPECT_EQ(arr3.size(), 6); EXPECT_EQ(arr3.size(), 6);
EXPECT_EQ(arr3[3], 19); EXPECT_EQ(arr3[3], 19);
EXPECT_EQ(arr3.pop(), 5); EXPECT_EQ(arr3.pop(), 5);
EXPECT_EQ(arr3.size(), 5); EXPECT_EQ(arr3.size(), 5);
arr3.resize(3); arr3.resize(3);
EXPECT_EQ(arr3.size(), 3); EXPECT_EQ(arr3.size(), 3);
EXPECT_EQ(arr3.capacity(), 3); EXPECT_EQ(arr3.capacity(), 3);
EXPECT_EQ(arr3.back(), 2); EXPECT_EQ(arr3.back(), 2);
arr3.resize(4); arr3.resize(4);
EXPECT_EQ(arr3.back(), 2); EXPECT_EQ(arr3.back(), 2);
arr3.push(17); arr3.push(17);
arr3.push(14); arr3.push(14);
EXPECT_EQ(arr3.back(), 14); EXPECT_EQ(arr3.back(), 14);
EXPECT_EQ(arr3.size(), 5); EXPECT_EQ(arr3.size(), 5);
arr3.clear(); arr3.clear();
EXPECT_EQ(arr3.is_empty(), true); EXPECT_EQ(arr3.is_empty(), true);
hpr::DynamicArray<float*> arr4; hpr::DynamicArray<float*> arr4;
arr4.push(new float(5)); arr4.push(new float(5));
arr4.push(new float(7)); arr4.push(new float(7));
arr4.push(new float(9)); arr4.push(new float(9));
EXPECT_EQ(*arr4[0], 5.f); EXPECT_EQ(*arr4[0], 5.f);
EXPECT_EQ(*arr4[2], 9.f); EXPECT_EQ(*arr4[2], 9.f);
for (auto& v : arr4) for (auto& v : arr4)
delete v; delete v;
} }
TEST(containers, TreeNode) TEST(containers, TreeNode)
{ {
hpr::TreeNode<float> node1 (5); hpr::TreeNode<float> node1 (5);
//std::shared_ptr<hpr::TreeNode<float>> ptr {node1}; //std::shared_ptr<hpr::TreeNode<float>> ptr {node1};
hpr::TreeNode<float> node2 {7, {&node1}}; hpr::TreeNode<float> node2 {7, {&node1}};
hpr::TreeNode<float> node3 {9, {&node2, &node1}}; hpr::TreeNode<float> node3 {9, {&node2, &node1}};
hpr::TreeNode<float> node4 {11, {&node3}}; hpr::TreeNode<float> node4 {11, {&node3}};
EXPECT_EQ(*node1.data(), 5); EXPECT_EQ(*node1.data(), 5);
//EXPECT_EQ(*node1->data(), *node2.ancestor()->data()); //EXPECT_EQ(*node1->data(), *node2.ancestor()->data());
hpr::darray<hpr::TreeNode<float>*> tr = node1.traverse_descendants(); hpr::darray<hpr::TreeNode<float>*> tr = node1.traverse_descendants();
EXPECT_EQ(tr.size(), 0); EXPECT_EQ(tr.size(), 0);
hpr::darray<hpr::TreeNode<float>*> tr2 = node4.traverse_descendants(); hpr::darray<hpr::TreeNode<float>*> tr2 = node4.traverse_descendants();
EXPECT_EQ(tr2.size(), 4); EXPECT_EQ(tr2.size(), 4);
hpr::darray<hpr::TreeNode<float>*> tr3 = node1.traverse_ancestors(); hpr::darray<hpr::TreeNode<float>*> tr3 = node1.traverse_ancestors();
EXPECT_EQ(tr3.size(), 2); // node1 has changed ancestor EXPECT_EQ(tr3.size(), 2); // node1 has changed ancestor
// //
} }

View File

@ -1,63 +1,63 @@
#pragma once #pragma once
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <hpr/math/vector.hpp> #include <hpr/math/vector.hpp>
#include <hpr/math/matrix.hpp> #include <hpr/math/matrix.hpp>
#include <hpr/math/quaternion.hpp> #include <hpr/math/quaternion.hpp>
TEST(math, Vector) TEST(math, Vector)
{ {
hpr::vec3 v1 {1, 3, 2}; hpr::vec3 v1 {1, 3, 2};
hpr::vec3 v2 {5, 7, -1}; hpr::vec3 v2 {5, 7, -1};
hpr::vec2 v31 {13, -2}; hpr::vec2 v31 {13, -2};
hpr::vec3 v32 (v31, 9); hpr::vec3 v32 (v31, 9);
EXPECT_EQ((hpr::vec3(v2.begin(), v2.end())), v2); EXPECT_EQ((hpr::vec3(v2.begin(), v2.end())), v2);
EXPECT_EQ(v32, hpr::vec3(13, -2, 9)); EXPECT_EQ(v32, hpr::vec3(13, -2, 9));
EXPECT_EQ(-v1, hpr::vec3(-1, -3, -2)); EXPECT_EQ(-v1, hpr::vec3(-1, -3, -2));
EXPECT_EQ(v1 + v2, hpr::vec3(6, 10, 1)); EXPECT_EQ(v1 + v2, hpr::vec3(6, 10, 1));
EXPECT_EQ(v1 - v2, hpr::vec3(-4, -4, 3)); EXPECT_EQ(v1 - v2, hpr::vec3(-4, -4, 3));
EXPECT_EQ((hpr::dot(v1, v2) ), 24); EXPECT_EQ((hpr::dot(v1, v2) ), 24);
EXPECT_EQ((hpr::cross(hpr::vec3(1, 0, 0), hpr::vec3(0, 1, 0))), hpr::vec3(0, 0, 1)); EXPECT_EQ((hpr::cross(hpr::vec3(1, 0, 0), hpr::vec3(0, 1, 0))), hpr::vec3(0, 0, 1));
EXPECT_EQ((hpr::angle(hpr::vec3(1, 0, 0), hpr::vec3(0, 0, 1))), hpr::pi() * 0.5); EXPECT_EQ((hpr::angle(hpr::vec3(1, 0, 0), hpr::vec3(0, 0, 1))), hpr::pi() * 0.5);
EXPECT_EQ((hpr::normalize(hpr::vec3(1, 1, 1))), hpr::vec3(0.5773502691896258, 0.5773502691896258, 0.5773502691896258)); EXPECT_EQ((hpr::normalize(hpr::vec3(1, 1, 1))), hpr::vec3(0.5773502691896258, 0.5773502691896258, 0.5773502691896258));
} }
TEST(math, Matrix) TEST(math, Matrix)
{ {
hpr::mat2 m1; hpr::mat2 m1;
hpr::vec4 v1; hpr::vec4 v1;
EXPECT_FALSE(v1 == m1); EXPECT_FALSE(v1 == m1);
EXPECT_FALSE(m1 == v1); EXPECT_FALSE(m1 == v1);
hpr::mat2 m2 {3, 2, 7, 4}; hpr::mat2 m2 {3, 2, 7, 4};
hpr::vec2 v2 {2, 4}; hpr::vec2 v2 {2, 4};
EXPECT_EQ(m2.col(1), v2); EXPECT_EQ(m2.col(1), v2);
hpr::vec2 v3 {13, 51}; hpr::vec2 v3 {13, 51};
m2.col(1, v3); m2.col(1, v3);
EXPECT_EQ(m2.col(1), v3); EXPECT_EQ(m2.col(1), v3);
hpr::mat3 m4 {1, 2, 3, 4, 5, 6, 7, 8, 9}; hpr::mat3 m4 {1, 2, 3, 4, 5, 6, 7, 8, 9};
hpr::mat2 m41 {5, 6, 8, 9}; hpr::mat2 m41 {5, 6, 8, 9};
//EXPECT_EQ(minor(m41, 0, 0), 9); //EXPECT_EQ(minor(m41, 0, 0), 9);
hpr::mat2 m5 {1, 2, 3, 4}; hpr::mat2 m5 {1, 2, 3, 4};
EXPECT_EQ(det(m4), 0); EXPECT_EQ(det(m4), 0);
EXPECT_EQ(hpr::det(m4), 0); EXPECT_EQ(hpr::det(m4), 0);
EXPECT_EQ(det(hpr::mat3(-9, 23, 3, 5, 5, 6, 7, -3, 9)), -786); EXPECT_EQ(det(hpr::mat3(-9, 23, 3, 5, 5, 6, 7, -3, 9)), -786);
hpr::mat2 m6 {2, 1, 7, 4}; hpr::mat2 m6 {2, 1, 7, 4};
EXPECT_EQ(det(m6), 1); EXPECT_EQ(det(m6), 1);
EXPECT_EQ(adj(m6), hpr::mat2(4, -1, -7, 2)); EXPECT_EQ(adj(m6), hpr::mat2(4, -1, -7, 2));
EXPECT_EQ(inv(m6), hpr::mat2(4, -1, -7, 2)); EXPECT_EQ(inv(m6), hpr::mat2(4, -1, -7, 2));
EXPECT_EQ(det(hpr::mat3(1, 0, 0, 0, 1, 0, 0, 0, 1)), 1.); EXPECT_EQ(det(hpr::mat3(1, 0, 0, 0, 1, 0, 0, 0, 1)), 1.);
//EXPECT_EQ(m4.det(), 0); //EXPECT_EQ(m4.det(), 0);
} }
TEST(math, Quaternion) TEST(math, Quaternion)
{ {
hpr::quat q; hpr::quat q;
hpr::vec3 np = hpr::rotate(hpr::vec3(0, 1, 0), {1, 0, 0}, hpr::pi() * 0.5); hpr::vec3 np = hpr::rotate(hpr::vec3(0, 1, 0), {1, 0, 0}, hpr::pi() * 0.5);
EXPECT_TRUE(hpr::all(hpr::equal(np, hpr::vec3(0, 0, 1)))); EXPECT_TRUE(hpr::all(hpr::equal(np, hpr::vec3(0, 0, 1))));
EXPECT_EQ(hpr::norm(hpr::quat(np)), 1); EXPECT_EQ(hpr::norm(hpr::quat(np)), 1);
} }

View File

@ -1,41 +1,41 @@
#pragma once #pragma once
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <hpr/numeric.hpp> #include <hpr/numeric.hpp>
#include <complex> #include <complex>
TEST(numeric, Scalar) TEST(numeric, Scalar)
{ {
EXPECT_EQ(hpr::scalar(5) + hpr::scalar(7), hpr::scalar(12)); EXPECT_EQ(hpr::scalar(5) + hpr::scalar(7), hpr::scalar(12));
#ifdef HPR_SCALAR_IMPLEMENTATION #ifdef HPR_SCALAR_IMPLEMENTATION
EXPECT_TRUE(std::is_floating_point_v<hpr::Scalar<double>>); EXPECT_TRUE(std::is_floating_point_v<hpr::Scalar<double>>);
EXPECT_TRUE(std::is_arithmetic_v<hpr::Scalar<double>>); EXPECT_TRUE(std::is_arithmetic_v<hpr::Scalar<double>>);
#endif #endif
//EXPECT_EQ(5.f, hpr::Scalar<double>(5)); //EXPECT_EQ(5.f, hpr::Scalar<double>(5));
EXPECT_EQ(hpr::rad(180), hpr::pi()); EXPECT_EQ(hpr::rad(180), hpr::pi());
EXPECT_EQ(hpr::deg(hpr::pi()), 180); EXPECT_EQ(hpr::deg(hpr::pi()), 180);
EXPECT_EQ(hpr::cos(0), 1); EXPECT_EQ(hpr::cos(0), 1);
EXPECT_EQ(hpr::sin(0), 0); EXPECT_EQ(hpr::sin(0), 0);
EXPECT_EQ(hpr::abs(hpr::scalar(-1)), 1); EXPECT_EQ(hpr::abs(hpr::scalar(-1)), 1);
EXPECT_EQ(hpr::pow(2, 2), 4); EXPECT_EQ(hpr::pow(2, 2), 4);
EXPECT_EQ(hpr::precision(), static_cast<hpr::scalar>(1e-15)); EXPECT_EQ(hpr::precision(), static_cast<hpr::scalar>(1e-15));
EXPECT_TRUE(typeid(static_cast<float>(hpr::scalar(5))) == typeid(float)); EXPECT_TRUE(typeid(static_cast<float>(hpr::scalar(5))) == typeid(float));
EXPECT_FALSE(!hpr::scalar(-1.)); EXPECT_FALSE(!hpr::scalar(-1.));
std::stringstream oss; std::stringstream oss;
oss << hpr::cos(0); oss << hpr::cos(0);
EXPECT_EQ(oss.str(), "1"); EXPECT_EQ(oss.str(), "1");
hpr::scalar s; hpr::scalar s;
oss >> s; oss >> s;
EXPECT_EQ(s, 1); EXPECT_EQ(s, 1);
EXPECT_TRUE(hpr::equal(5.5453535353535395818593, 5.5453535353535395817592, 1e-18)); EXPECT_TRUE(hpr::equal(5.5453535353535395818593, 5.5453535353535395817592, 1e-18));
EXPECT_EQ(hpr::min(7., 5), 5); EXPECT_EQ(hpr::min(7., 5), 5);
EXPECT_EQ(hpr::max(7., 5), 7); EXPECT_EQ(hpr::max(7., 5), 7);
EXPECT_EQ(hpr::clip(7., 5, 10), 7); EXPECT_EQ(hpr::clip(7., 5, 10), 7);
EXPECT_EQ(hpr::clip(1., 5, 10), 5); EXPECT_EQ(hpr::clip(1., 5, 10), 5);
EXPECT_EQ(hpr::clip(72., 5, 10), 10); EXPECT_EQ(hpr::clip(72., 5, 10), 10);
} }

View File

@ -1,72 +1,72 @@
target("hpr") target("hpr")
set_kind("shared") set_kind("shared")
set_languages("c++20") set_languages("c++20")
set_policy("build.c++.modules", false) set_policy("build.c++.modules", false)
add_options("scalar", "scalar_implementation") add_options("scalar", "scalar_implementation")
add_includedirs("..", { public = true }) add_includedirs("..", { public = true })
add_headerfiles("../(hpr/*.hpp)") add_headerfiles("../(hpr/*.hpp)")
add_headerfiles("../(hpr/*/*.hpp)") add_headerfiles("../(hpr/*/*.hpp)")
add_files("hpr.cpp") add_files("hpr.cpp")
-- export all symbols for windows/dll -- export all symbols for windows/dll
if is_plat("windows") and is_kind("shared") then if is_plat("windows") and is_kind("shared") then
if is_mode("release") then if is_mode("release") then
set_optimize("fastest") set_optimize("fastest")
end end
add_rules("utils.symbols.export_all") add_rules("utils.symbols.export_all")
end end
-- install importfiles for pkg-config/cmake -- install importfiles for pkg-config/cmake
add_rules("utils.install.cmake_importfiles") add_rules("utils.install.cmake_importfiles")
add_rules("utils.install.pkgconfig_importfiles") add_rules("utils.install.pkgconfig_importfiles")
-- add packages -- add packages
for _, name in ipairs({"imgui", "implot", "glfw", "opencascade"}) do for _, name in ipairs({"imgui", "implot", "glfw", "opencascade"}) do
add_packages(name) add_packages(name)
if has_package(name) then if has_package(name) then
set_configvar("HPR_HAVE_PACKAGE_" .. name:upper(), 1) set_configvar("HPR_HAVE_PACKAGE_" .. name:upper(), 1)
end end
end end
target_end() target_end()
target("tests") target("tests")
set_kind("binary") set_kind("binary")
set_default(false) set_default(false)
set_languages("c++20") set_languages("c++20")
if is_plat("mingw") or is_plat("windows") then if is_plat("mingw") or is_plat("windows") then
add_ldflags("-static", { force = true} ) add_ldflags("-static", { force = true} )
end end
set_policy("build.c++.modules", false) set_policy("build.c++.modules", false)
add_options("scalar", "scalar_implementation") add_options("scalar", "scalar_implementation")
add_packages("gtest") add_packages("gtest")
add_includedirs("..", { public = true }) add_includedirs("..", { public = true })
add_files("tests/main.cpp") add_files("tests/main.cpp")
on_load(function (target) on_load(function (target)
for _, file in ipairs(os.files("source/hpr/tests/test_*.cpp")) do for _, file in ipairs(os.files("source/hpr/tests/test_*.cpp")) do
target:add("files", file) target:add("files", file)
for line in io.lines(file) do for line in io.lines(file) do
local group, name = string.match(line:gsub("%s+", ""), "TEST%a*%((%a+),(%a+)%)") local group, name = string.match(line:gsub("%s+", ""), "TEST%a*%((%a+),(%a+)%)")
if group then if group then
target:add("tests", group .. "/" .. name, { group = group, runargs = "--gtest_filter=" .. group .. "." .. name}) target:add("tests", group .. "/" .. name, { group = group, runargs = "--gtest_filter=" .. group .. "." .. name})
end end
end end
end end
end) end)
target_end() target_end()

View File

@ -1,65 +1,65 @@
-- options: general -- options: general
option("creator") option("creator")
set_category("General") set_category("General")
set_default(false) set_default(false)
set_showmenu(true) set_showmenu(true)
set_description("Build creator application") set_description("Build creator application")
option_end() option_end()
option("tests") option("tests")
set_category("General") set_category("General")
set_default(false) set_default(false)
set_showmenu(true) set_showmenu(true)
set_description("Build tests") set_description("Build tests")
option_end() option_end()
-- options: modules -- options: modules
for _, name in ipairs({"csg", "mesh"}) do for _, name in ipairs({"csg", "mesh"}) do
option(name) option(name)
set_category("Modules") set_category("Modules")
set_default(true) set_default(true)
set_showmenu(true) set_showmenu(true)
set_description(format("Module %s", name)) set_description(format("Module %s", name))
set_configvar("HPR_HAVE_MODULE_" .. name:upper(), 1) set_configvar("HPR_HAVE_MODULE_" .. name:upper(), 1)
option_end() option_end()
end end
-- packages -- packages
add_requires("imgui v1.90-docking") add_requires("imgui v1.90-docking")
add_requires("implot v0.15") add_requires("implot v0.15")
add_requires("glfw 3.3.8") add_requires("glfw 3.3.8")
if has_config("csg") then if has_config("csg") then
add_requires("conan::opencascade/7.6.2") add_requires("pacman::opencascade 7.7.2", {alias = "opencascade"})
end end
if has_config("tests") then if has_config("tests") then
add_requires("gtest") add_requires("gtest")
end end
-- --
option("scalar_implementation") option("scalar_implementation")
set_category("Internal") set_category("Internal")
set_default(true) set_default(true)
set_description("Use internal scalar implementation") set_description("Use internal scalar implementation")
add_defines("HPR_SCALAR_IMPLEMENTATION") add_defines("HPR_SCALAR_IMPLEMENTATION")
option_end() option_end()
option("scalar") option("scalar")
set_category("Internal") set_category("Internal")
set_values("float", "double", "long double") set_values("float", "double", "long double")
set_default("float") set_default("float")
set_description("Internal scalar value type") set_description("Internal scalar value type")
after_check(function(option) after_check(function(option)
option:add("defines", format("HPR_SCALAR=%s", option:value())) option:add("defines", format("HPR_SCALAR=%s", option:value()))
end) end)
option_end() option_end()
-- includes project dirs -- includes project dirs
includes("hpr") includes("hpr")
if has_config("creator") then if has_config("creator") then
includes("creator") includes("creator")
end end

View File

@ -1,17 +1,17 @@
set_project("hpr") set_project("hpr")
set_version("0.0.1") set_version("0.0.1")
add_rules("mode.debug", "mode.release") add_rules("mode.debug", "mode.release")
if is_mode("debug") then if is_mode("debug") then
add_defines("HPR_DEBUG") add_defines("HPR_DEBUG")
end end
if is_plat("linux") and is_mode("debug") then if is_plat("linux") and is_mode("debug") then
add_ldflags("-rdynamic") add_ldflags("-rdynamic")
end end
set_optimize("fastest") set_optimize("fastest")
includes("source") includes("source")