Skip to content

Commit d143aef

Browse files
authored
Refactor structure (#3)
- put sorting network implementations in separate files - put tests for each network implementation in a separate file (allows for faster compilation) - add githook to automatically create a single header implementation - update readme - add .clangformat
1 parent 6b691c1 commit d143aef

28 files changed

+2352
-1198
lines changed

.clang-format

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
AlignConsecutiveAssignments: false
3+
AllowShortFunctionsOnASingleLine: Inline
4+
AllowShortIfStatementsOnASingleLine: Never
5+
AllowShortLambdasOnASingleLine: Inline
6+
AllowShortLoopsOnASingleLine: 'false'
7+
AlignConsecutiveDeclarations: 'false'
8+
AlwaysBreakAfterDefinitionReturnType: None
9+
AlwaysBreakAfterReturnType: None
10+
AlwaysBreakTemplateDeclarations: Yes
11+
BreakBeforeBinaryOperators: None
12+
BreakBeforeBraces: Custom
13+
BraceWrapping:
14+
SplitEmptyRecord: false
15+
AfterClass: true
16+
AfterFunction: true
17+
AfterNamespace: true
18+
AfterStruct: true
19+
AfterControlStatement: Always
20+
AfterEnum: true
21+
AfterUnion: true
22+
AfterExternBlock: true
23+
BeforeCatch: true
24+
BeforeElse: false
25+
# BeforeLambdaBody: false
26+
# BeforeWhile: false
27+
SplitEmptyFunction: false
28+
SplitEmptyNamespace: false
29+
BreakInheritanceList: BeforeColon
30+
BreakStringLiterals: 'true'
31+
ColumnLimit: '120'
32+
CompactNamespaces: 'false'
33+
ConstructorInitializerIndentWidth: '2'
34+
ContinuationIndentWidth: '2'
35+
DerivePointerAlignment: 'true'
36+
DisableFormat: 'false'
37+
IncludeBlocks: Regroup
38+
IndentCaseLabels: 'true'
39+
IndentWidth: '2'
40+
IndentWrappedFunctionNames: 'true'
41+
KeepEmptyLinesAtTheStartOfBlocks: 'false'
42+
Language: Cpp
43+
MaxEmptyLinesToKeep: '2'
44+
NamespaceIndentation: All
45+
PenaltyBreakAssignment: '50'
46+
PointerAlignment: Left
47+
ReflowComments: 'true'
48+
SortIncludes: 'false'
49+
SortUsingDeclarations: 'false'
50+
SpaceAfterCStyleCast: 'false'
51+
SpaceAfterLogicalNot: 'false'
52+
SpaceAfterTemplateKeyword: 'false'
53+
SpaceBeforeAssignmentOperators: 'true'
54+
SpaceBeforeCpp11BracedList: 'false'
55+
SpaceBeforeCtorInitializerColon: 'true'
56+
SpaceBeforeInheritanceColon: 'true'
57+
SpaceBeforeParens: ControlStatements
58+
SpaceInEmptyParentheses: 'false'
59+
SpacesBeforeTrailingComments: '2'
60+
SpacesInAngles: 'false'
61+
SpacesInCStyleCastParentheses: 'false'
62+
SpacesInParentheses: 'false'
63+
SpacesInSquareBrackets: 'false'
64+
Standard: Auto
65+
TabWidth: '0'
66+
UseTab: Never
67+
68+
...

.githooks/pre-push

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/sh
2+
3+
echo 'Creating single header implementation'
4+
LOCAL_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
5+
py "$LOCAL_DIR/../scripts/make_single_header_impl.py"
6+
7+
git add "single_header_impl"
8+
9+
if ! git diff --quiet --cached single_header_impl; then
10+
echo "Contents of single_header_impl changed. Please check whether these changes are correct."
11+
exit -1
12+
fi

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
.idea
2-
cmake-build*
2+
cmake-build*
3+
.vs
4+
out

CMakeLists.txt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,15 @@ endif()
3939
if(BUILD_TESTS)
4040
find_package(GTest REQUIRED)
4141
include(GoogleTest)
42-
enable_testing()
4342

44-
add_executable(${SN_TESTS_EXECUTABLE_NAME} "test/test_case_gen.h" "test/sorting_network_tests.cpp")
43+
add_executable(${SN_TESTS_EXECUTABLE_NAME}
44+
"test/test_base.h"
45+
"test/test_batcher_odd_even_merge_sort.cpp"
46+
"test/test_bitonic_merge_sort.cpp"
47+
"test/test_bose_nelson_sort.cpp"
48+
"test/test_bubble_sort.cpp"
49+
"test/test_insertion_sort.cpp"
50+
"test/test_size_optimized_sort.cpp"
51+
)
4552
target_link_libraries(${SN_TESTS_EXECUTABLE_NAME} GTest::gtest GTest::gtest_main metal project_options)
46-
47-
gtest_discover_tests(${SN_TESTS_EXECUTABLE_NAME})
4853
endif()

README.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ A single class `sorting_network` is available which encapsulates the implementat
2222
Following listing gives a few examples:
2323

2424
```cpp
25-
#include <sorting_network_cpp/sorting_network.hpp>
25+
#include <sorting_network_cpp/sorting_network.h>
2626

2727
#include <array>
2828
#include <cstdint>
@@ -57,7 +57,7 @@ void example()
5757
// may be passed as follows:
5858

5959
// custom comparators
60-
sorting_network<N>{}(data, compare_and_swap<int, std::less<int>>{});
60+
sorting_network<N>{}(data, compare_and_swap<int, std::less<>>{});
6161

6262
// function objects
6363
struct predicate
@@ -90,20 +90,23 @@ quxflux::sorting_net::sorting_network<N, quxflux::sorting_net::type::bitonic_mer
9090
The compare and swap operation is the fundamental element a sorting network is composed of. The default implementation works well on scalar types, but if you want to specify a custom implementation (e.g. when hardware intrinsics should be used) you may do this by providing a compare and swap functor to the `sorting_network::operator()` as in following example:
9191

9292
```cpp
93-
#include <sorting_network_cpp/sorting_network.hpp>
93+
#include <sorting_network_cpp/sorting_network.h>
9494

9595
#include <array>
9696

9797
void example(std::array<float,3>& arr)
9898
{
99-
quxflux::sorting_net::sorting_network<3>{}(arr, [](float& a, float& b){
99+
quxflux::sorting_net::sorting_network<3>{}(arr.begin(), [](float& a, float& b){
100100
const auto b_cpy = b;
101101
b = std::max(a, b);
102102
a = std::min(a, b_cpy);
103103
});
104104
}
105105
```
106106
107+
## Single header implementation
108+
A single header implementation is available which allows experimenting with the sorting networks on [godbolt](https://godbolt.org/z/69WMqMY3c).
109+
107110
## Requirements
108111
A compiler with C++17 support
109112
@@ -114,6 +117,11 @@ For the bare sorting functionality no dependencies are required. If you want to
114117
* Depending on the implementation of the comparator the performance advantage of a sorting net compared to a regular sorting algorithm (e.g. `std::sort`) may diminish or even result in worse performance. This can be seen in the [interactive benchmark results overview](https://raw.githack.com/quxflux/sorting_network_cpp/master/doc/data_explorer.htm) for the data type `Vec2i Z-order` which causes in most cases all variants of sorting networks being outperformed by `std::sort` (see [src/benchmark.cpp](src/benchmark.cpp) for the implementation of the aforementioned data type).
115118
* msvc will fail compiling larger `insertion_sort` networks in certain (unknown) configurations with `fatal error C1202: recursive type or function dependency context too complex`
116119
120+
## Development notes
121+
* A pre-push [githook](https://git-scm.com/docs/githooks) is available in [.githooks](./.githooks/) which will automatically create the single header implementation.
122+
To enable the hook execute
123+
`git config --local core.hooksPath .githooks` in the repository directory (python required)
124+
117125
## References / Acknowledgements
118126
* ["A Sorting Problem"](https://dl.acm.org/doi/pdf/10.1145/321119.321126) by Bose et al.
119127
* ["Sorting networks and their applications"](https://core.ac.uk/download/pdf/192393620.pdf) by Batcher
@@ -125,4 +133,4 @@ For the bare sorting functionality no dependencies are required. If you want to
125133
* [Chart.js](https://www.chartjs.org/) and [Papa Parse](https://www.papaparse.com/) for the visualization of benchmark results
126134
127135
## License
128-
[GPLv3](LICENSE)
136+
[GPLv3](LICENSE)

0 commit comments

Comments
 (0)