stage changes
This commit is contained in:
parent
38d628d4ef
commit
39b2063889
66
.clang-format
Normal file
66
.clang-format
Normal 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
24
.gitignore
vendored
@ -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
15
.vscode/c_cpp_properties.json
vendored
Normal 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
26
.vscode/compile_commands.json
vendored
Normal 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"
|
||||||
|
}]
|
@ -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>
|
||||||
|
@ -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
|
@ -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
|
||||||
|
@ -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
|
@ -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
|
||||||
|
@ -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
|
@ -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
|
@ -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>
|
||||||
|
@ -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
@ -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
|
@ -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
|
@ -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
3
source/hpr/shape.hpp
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <hpr/shape/shape.hpp>
|
360
source/hpr/shape/shape.hpp
Normal file
360
source/hpr/shape/shape.hpp
Normal 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
5
source/hpr/shape/shape_impl_occ.cpp
Normal file
5
source/hpr/shape/shape_impl_occ.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
128
source/xmake.lua
128
source/xmake.lua
@ -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
|
32
xmake.lua
32
xmake.lua
@ -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")
|
Loading…
Reference in New Issue
Block a user