Skip to content

Commit

Permalink
v2.0.0 - see changelog for info -- breaking change with how we evalua…
Browse files Browse the repository at this point in the history
…te operations/functions of length 1 vectors
  • Loading branch information
davidbrowne committed May 9, 2024
1 parent f5cb428 commit 714f6df
Show file tree
Hide file tree
Showing 11 changed files with 776 additions and 435 deletions.
28 changes: 20 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
# dsga : Data Structures for Geometric Algorithms

**dsga** is a single header-only **C++20 library** that implements the **vectors** and **matrices** from the OpenGL Shading Language 4.6 specification ([pdf](https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.pdf) | [html](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.html)). It is inspired by the spec, but does deviate in some small ways, mostly to make it work well in C++20. It is not intended to be used for rendering, just for sharing the fundamental data structures and associated functions. Our requirements in general are for things like 3D CAD/CAM applications and other geometric and algebraic things. See [motivation](docs/MOTIVATION.md) for more details. This library does not use SIMD instructions or types under the hood, beyond whatever the compiler provides through optimization.
**dsga** is a single header-only **C++20 library** that implements the **vectors** and **matrices** from the OpenGL Shading Language 4.6 specification ([pdf](https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.pdf) | [html](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.html)). It is inspired by the spec, but does deviate in some small ways, mostly to make it work well in C++20. It is intended to be used for [array programming](https://en.wikipedia.org/wiki/Array_programming) other than rendering. Our requirements in general are for things like 3D CAD/CAM applications and other geometric and algebraic things. See [motivation](docs/MOTIVATION.md) for more details. This library does _not_ use SIMD instructions or types under the hood, beyond whatever the compiler provides through optimization.

## Home
[https://github.com/davidbrowne/dsga](https://github.com/davidbrowne/dsga)

## Current Version
v1.5.0
v2.0.0

## [Latest Major Changes](docs/CHANGELOG.md)

* v2.0.0
* Large __Breaking Change__ - minimized how vectors of length == 1 behave as vectors. Most dsga operations and functions treat length == 1 vectors as scalars, returning scalar results (mostly through refactoring the underlying execution machinery). Use of the non-GLSL types iscal, uscal, bscal, scal, fscal, dscal, etc., is generally discouraged.
* Small __Breaking Change__ - reverted/removed ```std::initializer_list``` constructors added in v1.5.0.
* Added ```within_tolerance()``` comparison functions, that fit well with ```within_distance()``` and ```within_box()```.

* v1.5.0
* Small __Breaking Change__ - added ```std::initializer_list``` constructors to ```basic_vector``` and ```basic_matrix``` - if not enough components, then fill rest with zeros - if too many components, just use the components necessary to fill the vector or matrix.
* Fixed ```indexed_vector``` iterator classes to use signed types for indexing into storage (fixes iterator subtraction and ```reverse_iterator``` usage, as the iterators are random-access).

## Minimum Version of Tested Compilers
* Microsoft Visual Studio 2022 v17.x
Expand Down Expand Up @@ -193,7 +204,7 @@ template <dsga::floating_point_scalar T1, dsga::floating_point_scalar T2>
```
## Relevant GLSL Overview

Our programming environment is ```c++20```, not a GLSL shader program, so the entire GLSL Shading language specification is a super-set of what we are trying to achieve. We really just want the vector and matrix data structures (and their corresponding functions and behavior) to be usable in a ```c++20``` environment.
Our programming environment is ```C++20```, not a GLSL shader program, so the entire GLSL Shading language specification is a super-set of what we are trying to achieve. We really just want the vector and matrix data structures (and their corresponding functions and behavior) to be usable in a ```C++20``` environment. Another term for this type of programming is [array programming](https://en.wikipedia.org/wiki/Array_programming).

The following links to the shading specification should help with understanding what we are trying to implement with this header-only library.

Expand Down Expand Up @@ -311,10 +322,11 @@ This is a c++20 library, so that needs to be the minimum standard that you tell
## Status
Current version: `v1.5.0`
Current version: `v2.0.0`
* Everything major has some tests, but code coverage is not 100%.
* [Last Released: v1.5.0](https://github.com/davidbrowne/dsga/releases/tag/v1.5.0)
* [Last Released: v2.0.0](https://github.com/davidbrowne/dsga/releases/tag/v2.0.0)
* [Change Log](docs/CHANGELOG.md)
### The next steps
* Refining API documentation.
Expand Down Expand Up @@ -361,7 +373,7 @@ The tests have been most recently run on:
[doctest] Status: SUCCESS!
```
* **clang 18.1.3** on Windows, [official binaries](https://github.com/llvm/llvm-project/releases/tag/llvmorg-18.1.3), with MSVC and/or gcc 13.2.0 installed:
* **clang 18.1.5** on Windows, [official binaries](https://github.com/llvm/llvm-project/releases/tag/llvmorg-18.1.5), with MSVC and/or gcc 13.2.0 installed:
Performs all the unit tests except where there is lack of support for ```std::is_corresponding_member<>```, and this is protected with a feature test macro.
Expand All @@ -374,7 +386,7 @@ Performs all the unit tests except where there is lack of support for ```std::is
[doctest] Status: SUCCESS!
```
### Ubuntu Noble Numbat preview running in WSL2 for Windows 11
### Ubuntu 24.04 LTS running in WSL2 for Windows 11
* **gcc 14.0.1**
Expand All @@ -387,7 +399,7 @@ Performs all the unit tests except where there is lack of support for ```std::is
[doctest] Status: SUCCESS!
```
* **clang 18.1.0rc2**
* **clang 18.1.3**
Performs all the unit tests except where there is lack of support for ```std::is_corresponding_member<>```, and this is protected with a feature test macro.
Expand Down
1 change: 1 addition & 0 deletions VS2022/dsga.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@
</ItemGroup>
<ItemGroup>
<None Include="..\docs\API.md" />
<None Include="..\docs\CHANGELOG.md" />
<None Include="..\docs\DETAILS.md" />
<None Include="..\docs\DOCUMENTATION.md" />
<None Include="..\docs\dsga.puml" />
Expand Down
1 change: 1 addition & 0 deletions VS2022/dsga.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
<Filter>Resource Files</Filter>
</None>
<None Include="..\docs\API.md" />
<None Include="..\docs\CHANGELOG.md" />
</ItemGroup>
<ItemGroup>
<Text Include="..\LICENSE_1_0.txt" />
Expand Down
83 changes: 64 additions & 19 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ template <typename UnOp>
requires (std::same_as<T, std::invoke_result_t<UnOp, T>> || std::same_as<T, std::invoke_result_t<UnOp, const T &>>)
[[nodiscard]] constexpr basic_vector<T, Count> apply(UnOp op) const noexcept;
```
Applies a lambda/function/function object/callable to every element of a vector, in an unspecified order. The callable must take either a ```T``` or ```const T &```, and it must return a ```T```. Returns a vector of the results.
Applies a lambda/function/function object/callable to every element of a vector, in element order (order only matters if callable is side-effecting and/or has state). The callable must take either a ```T``` or ```const T &```, and it must return a ```T```. Returns a vector of the results.

##### ```vector_base::shift```
```c++
Expand Down Expand Up @@ -1822,6 +1822,7 @@ Most of the functions perform their operation component-wise. There are some fun
* [```none```](#none)
* [```logicalNot```](#logicalnot)
* Tolerance Checking Functions
* [```within_tolerance```](#within_tolerance)
* [```within_distance```](#within_distance)
* [```within_box```](#within_box)
* Other Vector Functions
Expand Down Expand Up @@ -1976,15 +1977,15 @@ Not in GLSL. May or may not actually be faster that ```rsqrt()```, for which thi

##### ```abs```
```c++
template <bool W, dimensional_scalar T, std::size_t C, typename D>
requires (!unsigned_scalar<T>) && non_bool_scalar<T>
template <bool W, non_bool_scalar T, std::size_t C, typename D>
requires (!unsigned_scalar<T>)
[[nodiscard]] constexpr auto abs(const vector_base<W, T, C, D> &arg) noexcept;
```

##### ```sign```
```c++
template <bool W, dimensional_scalar T, std::size_t C, typename D>
requires (!unsigned_scalar<T>) && non_bool_scalar<T>
template <bool W, non_bool_scalar T, std::size_t C, typename D>
requires (!unsigned_scalar<T>)
[[nodiscard]] constexpr auto sign(const vector_base<W, T, C, D> &arg) noexcept;
```

Expand Down Expand Up @@ -2257,17 +2258,23 @@ template <bool W1, floating_point_scalar T1, std::size_t C, typename D1, bool W2
template <bool W1, floating_point_scalar T1, typename D1, bool W2, floating_point_scalar T2, typename D2>
[[nodiscard]] constexpr auto cross(const vector_base<W1, T1, 3, D1> &a,
const vector_base<W2, T2, 3, D2> &b) noexcept;

template <floating_point_scalar T1, floating_point_scalar T2>
[[nodiscard]] constexpr auto cross(const basic_vector<T1, 3> &a,
const basic_vector<T2, 3> &b) noexcept;
```

##### ```normalize```
```c++
template <bool W, floating_point_scalar T, std::size_t C, typename D>
requires (C > 1)
[[nodiscard]] constexpr auto normalize(const vector_base<W, T, C, D> &x) noexcept;
```

##### ```faceforward```
```c++
template <bool W1, floating_point_scalar T, std::size_t C, typename D1, bool W2, typename D2, bool W3, typename D3>
requires (C > 1)
[[nodiscard]] constexpr auto faceforward(const vector_base<W1, T, C, D1> &n,
const vector_base<W2, T, C, D2> &i,
const vector_base<W3, T, C, D3> &nref) noexcept;
Expand All @@ -2276,13 +2283,15 @@ template <bool W1, floating_point_scalar T, std::size_t C, typename D1, bool W2,
##### ```reflect```
```c++
template <bool W1, floating_point_scalar T, std::size_t C, typename D1, bool W2, typename D2>
requires (C > 1)
[[nodiscard]] constexpr auto reflect(const vector_base<W1, T, C, D1> &i,
const vector_base<W2, T, C, D2> &n) noexcept;
```

##### ```refract```
```c++
template <bool W1, floating_point_scalar T, std::size_t C, typename D1, bool W2, typename D2>
requires (C > 1)
[[nodiscard]] constexpr auto refract(const vector_base<W1, T, C, D1> &i,
const vector_base<W2, T, C, D2> &n,
T eta) noexcept;
Expand Down Expand Up @@ -2373,44 +2382,80 @@ This function takes the place of GLSL function ```not```. We can't define a func

#### Tolerance Checking Functions

##### ```within_tolerance```
```c++
template <non_bool_scalar T, non_bool_scalar U>
requires implicitly_convertible_to<U, T>
[[nodiscard]] constexpr bool within_tolerance(T x,
U tolerance) noexcept;

template <bool W, non_bool_scalar T, std::size_t C, typename D, non_bool_scalar U>
requires implicitly_convertible_to<U, T>
[[nodiscard]] constexpr bool within_tolerance(const vector_base<W, T, C, D> &x,
U tolerance) noexcept;

template <bool W1, non_bool_scalar T, std::size_t C1, typename D1, bool W2, non_bool_scalar U, std::size_t C2, typename D2>
requires ((C1 == C2) || (C2 == 1)) && implicitly_convertible_to<U, T>
[[nodiscard]] constexpr bool within_tolerance(const vector_base<W1, T, C1, D1> &x,
const vector_base<W2, U, C2, D2> &tolerance) noexcept;
```
Not in GLSL. Is a vector of values (or a single value) the same as 0 within a tolerance (or vector of tolerances). The tolerance is a less-than-or-equal comparison. Tolerances need to be non-negative, or the function will assert.

##### ```within_distance```
```c++
template <bool W1, non_bool_scalar T, std::size_t C, typename D1, bool W2, typename D2>
template <non_bool_scalar T, non_bool_scalar U>
requires implicitly_convertible_to<U, T>
[[nodiscard]] constexpr bool within_distance(T x,
T y,
U tolerance) noexcept;

template <bool W1, non_bool_scalar T, std::size_t C, typename D1, bool W2, typename D2, non_bool_scalar U>
requires implicitly_convertible_to<U, T>
[[nodiscard]] constexpr bool within_distance(const vector_base<W1, T, C, D1> &x,
const vector_base<W2, T, C, D2> &y,
T tolerance) noexcept;
U tolerance) noexcept;

template <bool W1, non_bool_scalar T, std::size_t C, typename D1, bool W2, typename D2, bool W3, typename D3>
template <bool W1, non_bool_scalar T, std::size_t C, typename D1, bool W2, typename D2, bool W3, non_bool_scalar U, typename D3>
requires implicitly_convertible_to<U, T>
[[nodiscard]] constexpr bool within_distance(const vector_base<W1, T, C, D1> &x,
const vector_base<W2, T, C, D2> &y,
const vector_base<W3, T, 1, D3> &tolerance) noexcept;

const vector_base<W3, U, 1, D3> &tolerance) noexcept;
```
Not in GLSL. It compares the Euclidean distance between two vectors to see if they are within the tolerance. The tolerance is a strictly less-than comparison. Tolerances need to be non-negative.
Not in GLSL. It compares the Euclidean distance between two vectors to see if the distance is 0 within the tolerance. The tolerance is a less-than-or-equal comparison. Tolerances need to be non-negative, or the function will assert.

##### ```within_box```
```c++
template <bool W1, non_bool_scalar T, std::size_t C, typename D1, bool W2, typename D2>
requires non_bool_scalar<T>
template <non_bool_scalar T, non_bool_scalar U>
requires implicitly_convertible_to<U, T>
[[nodiscard]] constexpr bool within_box(T x,
T y,
U tolerance) noexcept;

template <bool W1, non_bool_scalar T, std::size_t C, typename D1, bool W2, typename D2, non_bool_scalar U>
requires implicitly_convertible_to<U, T>
[[nodiscard]] constexpr bool within_box(const vector_base<W1, T, C, D1> &x,
const vector_base<W2, T, C, D2> &y,
T tolerance) noexcept;
U tolerance) noexcept;

template <bool W1, non_bool_scalar T, std::size_t C1, typename D1, bool W2, typename D2, bool W3, std::size_t C2, typename D3>
requires ((C1 == C2) || (C2 == 1))
template <bool W1, non_bool_scalar T, std::size_t C1, typename D1, bool W2, typename D2, bool W3, non_bool_scalar U, std::size_t C2, typename D3>
requires ((C1 == C2) || (C2 == 1)) && implicitly_convertible_to<U, T>
[[nodiscard]] constexpr bool within_box(const vector_base<W1, T, C1, D1> &x,
const vector_base<W2, T, C1, D2> &y,
const vector_base<W3, T, C2, D3> &tolerance) noexcept;
const vector_base<W3, U, C2, D3> &tolerance) noexcept;
```
Not in GLSL. This represents a bounding-box tolerance check, which aggregates the component-wise tolerance checks. These functions can take a single tolerance or a vector of tolerances. All the vector elements must be within tolerance or the whole answer is false. The tolerance is a strictly less-than comparison. All tolerances need to be non-negative.
Not in GLSL. This represents a bounding-box tolerance check, which aggregates the component-wise tolerance checks. These functions can take a single tolerance or a vector of tolerances and check if the differences of the value(s) are 0 within the tolerance(s). All the vector elements must be within tolerance or the whole answer is false. The tolerance is a less-than-or-equal comparison. All tolerances need to be non-negative, or the function will assert.

##### ```swizzle```
```c++
template <bool W, dimensional_scalar T, std::size_t C, typename D, typename Arg>
requires std::convertible_to<Arg, std::size_t>
inline auto swizzle(const vector_base<W, T, C, D> &v, const Arg &index);

template <bool W, dimensional_scalar T, std::size_t C, typename D, typename ...Args>
requires (std::convertible_to<Args, std::size_t> && ...) && (sizeof...(Args) > 0) && (sizeof...(Args) <= 4)
inline basic_vector<T, sizeof...(Args)> swizzle(const vector_base<W, T, C, D> &v, const Args &...Is);
```
Not in GLSL. Runtime function for swizzling. Returns a stand-alone ```dsga::basic_vector``` version of a swizzle, instead of a ```dsga::indexed_vector``` data member. If the index arguments are invalid (out of bounds), this function will throw a ```std::out_of_range()``` exception. Inspired by the [Odin Programming Language](https://odin-lang.org/docs/overview/#swizzle-operations).
Not in GLSL. Runtime function for swizzling. Returns a stand-alone ```dsga::basic_vector``` version of a swizzle, instead of a ```dsga::indexed_vector``` data member. Will return a scalar value if only one index argument. If the index arguments are invalid (out of bounds), this function will throw a ```std::out_of_range()``` exception. Inspired by the [Odin Programming Language](https://odin-lang.org/docs/overview/#swizzle-operations).

### Scalar Functions
Scalar versions of most of the vector free functions exist. It is not recommended to use them if there is a function in the C++ Standard Library that does the same thing.
Expand Down
24 changes: 24 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Change Log

### v2.0.0
* Large __Breaking Change__ - minimized how vectors of length == 1 behave as vectors. Most dsga operations and functions treat length == 1 vectors as scalars, returning scalar results (mostly through refactoring the underlying execution machinery). Use of the non-GLSL types iscal, uscal, bscal, scal, fscal, dscal, etc., is generally discouraged.
* Small __Breaking Change__ - reverted/removed ```std::initializer_list``` constructors added in v1.5.0.
* Moved vector relational functions above the other vector functions (for use in assertions).
* Added ```within_tolerance()``` comparison functions, that fit well with ```within_distance()``` and ```within_box()```.
* Upgraded to cxcm v1.1.2.
* Minor type constraint (concepts) refactoring.
* Other minor refactoring.
* Added changelog.

### v1.5.0
* Small __Breaking Change__ - added ```std::initializer_list``` constructors to ```basic_vector``` and ```basic_matrix``` - if not enough components, then fill rest with zeros - if too many components, just use the components necessary to fill the vector or matrix.
* Fixed ```indexed_vector``` iterator classes to use signed types for indexing into storage (fixes iterator subtraction and ```reverse_iterator``` usage, as the iterators are random-access).

### v1.4.1
* Minor refactoring.
* Comment removal and/or updating.
* Removed Microsoft VS2019 support (latest version of VS2019 does not compile dsga).

### v1.4.0
* Minor type constraint (concepts) refactoring.
* Updating copyright dates.
Loading

0 comments on commit 714f6df

Please sign in to comment.