peclet-morton 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- peclet_morton-0.1.0/.github/workflows/ci.yml +155 -0
- peclet_morton-0.1.0/.github/workflows/docs.yml +50 -0
- peclet_morton-0.1.0/.github/workflows/quality.yml +26 -0
- peclet_morton-0.1.0/.github/workflows/release.yml +55 -0
- peclet_morton-0.1.0/.gitignore +17 -0
- peclet_morton-0.1.0/CLAUDE.md +118 -0
- peclet_morton-0.1.0/CMakeLists.txt +126 -0
- peclet_morton-0.1.0/DEVELOPMENT.md +166 -0
- peclet_morton-0.1.0/LICENSE +21 -0
- peclet_morton-0.1.0/PKG-INFO +207 -0
- peclet_morton-0.1.0/README.md +194 -0
- peclet_morton-0.1.0/benchmarks/CMakeLists.txt +20 -0
- peclet_morton-0.1.0/benchmarks/bench.cpp +170 -0
- peclet_morton-0.1.0/benchmarks/bench_batch.cpp +88 -0
- peclet_morton-0.1.0/benchmarks/bench_kokkos.cpp +73 -0
- peclet_morton-0.1.0/bindings/CMakeLists.txt +11 -0
- peclet_morton-0.1.0/bindings/morton_c.cpp +302 -0
- peclet_morton-0.1.0/bindings/python/bench_python.py +40 -0
- peclet_morton-0.1.0/bindings/python/peclet/morton/__init__.py +226 -0
- peclet_morton-0.1.0/bindings/python/tests/test_mortonarith.py +88 -0
- peclet_morton-0.1.0/cmake/morton-config.cmake.in +5 -0
- peclet_morton-0.1.0/conanfile.py +54 -0
- peclet_morton-0.1.0/docs/Doxyfile +43 -0
- peclet_morton-0.1.0/docs/EVALUATION.md +103 -0
- peclet_morton-0.1.0/docs/HILBERT_GPU_NOTES.md +86 -0
- peclet_morton-0.1.0/docs/ROADMAP.md +132 -0
- peclet_morton-0.1.0/include/morton/batch.hpp +172 -0
- peclet_morton-0.1.0/include/morton/hd.hpp +31 -0
- peclet_morton-0.1.0/include/morton/iterate.hpp +230 -0
- peclet_morton-0.1.0/include/morton/kokkos.hpp +218 -0
- peclet_morton-0.1.0/include/morton/morton.hpp +527 -0
- peclet_morton-0.1.0/include/morton/simd.hpp +208 -0
- peclet_morton-0.1.0/include/morton/wide_uint.hpp +174 -0
- peclet_morton-0.1.0/legacy/bitarray.hpp +996 -0
- peclet_morton-0.1.0/legacy/morton.hpp +259 -0
- peclet_morton-0.1.0/legacy/octree.hpp +371 -0
- peclet_morton-0.1.0/legacy/octree_visualize.ipynb +94 -0
- peclet_morton-0.1.0/octree/CMakeLists.txt +43 -0
- peclet_morton-0.1.0/octree/PLAN.md +61 -0
- peclet_morton-0.1.0/octree/README.md +45 -0
- peclet_morton-0.1.0/octree/include/morton_octree/octree.hpp +145 -0
- peclet_morton-0.1.0/octree/tests/test_main.cpp +2 -0
- peclet_morton-0.1.0/octree/tests/test_octree.cpp +110 -0
- peclet_morton-0.1.0/packaging/vcpkg/morton/portfile.cmake +30 -0
- peclet_morton-0.1.0/packaging/vcpkg/morton/vcpkg.json +11 -0
- peclet_morton-0.1.0/pyproject.toml +63 -0
- peclet_morton-0.1.0/tests/CMakeLists.txt +13 -0
- peclet_morton-0.1.0/tests/kokkos/CMakeLists.txt +9 -0
- peclet_morton-0.1.0/tests/kokkos/test_kokkos.cpp +124 -0
- peclet_morton-0.1.0/tests/test_arithmetic.cpp +136 -0
- peclet_morton-0.1.0/tests/test_batch.cpp +156 -0
- peclet_morton-0.1.0/tests/test_constexpr.cpp +48 -0
- peclet_morton-0.1.0/tests/test_encode_decode.cpp +101 -0
- peclet_morton-0.1.0/tests/test_iterate.cpp +77 -0
- peclet_morton-0.1.0/tests/test_main.cpp +2 -0
- peclet_morton-0.1.0/tests/test_neighbors.cpp +98 -0
- peclet_morton-0.1.0/tests/test_wide.cpp +153 -0
- peclet_morton-0.1.0/third_party/doctest.h +7106 -0
- peclet_morton-0.1.0/third_party/libmorton/morton.h +106 -0
- peclet_morton-0.1.0/third_party/libmorton/morton2D.h +283 -0
- peclet_morton-0.1.0/third_party/libmorton/morton2D_LUTs.h +120 -0
- peclet_morton-0.1.0/third_party/libmorton/morton3D.h +283 -0
- peclet_morton-0.1.0/third_party/libmorton/morton3D_LUTs.h +225 -0
- peclet_morton-0.1.0/third_party/libmorton/morton_AVX512BITALG.h +223 -0
- peclet_morton-0.1.0/third_party/libmorton/morton_BMI.h +60 -0
- peclet_morton-0.1.0/third_party/libmorton/morton_common.h +49 -0
- peclet_morton-0.1.0/third_party/libmorton_morton.h +106 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, "**"]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
# ---- C++ tests on Linux/macOS, gcc & clang, BMI2 on/off, Debug/Release ----
|
|
11
|
+
cpp:
|
|
12
|
+
name: ${{ matrix.os }} / ${{ matrix.cc }} / bmi2=${{ matrix.bmi2 }} / ${{ matrix.build_type }}
|
|
13
|
+
runs-on: ${{ matrix.os }}
|
|
14
|
+
strategy:
|
|
15
|
+
fail-fast: false
|
|
16
|
+
matrix:
|
|
17
|
+
os: [ubuntu-latest, macos-latest]
|
|
18
|
+
bmi2: [ON, OFF]
|
|
19
|
+
build_type: [Debug, Release]
|
|
20
|
+
include:
|
|
21
|
+
- os: ubuntu-latest
|
|
22
|
+
cc: gcc
|
|
23
|
+
cxx: g++
|
|
24
|
+
- os: macos-latest
|
|
25
|
+
cc: clang
|
|
26
|
+
cxx: clang++
|
|
27
|
+
# also run clang on Linux
|
|
28
|
+
exclude: []
|
|
29
|
+
env:
|
|
30
|
+
CC: ${{ matrix.cc }}
|
|
31
|
+
CXX: ${{ matrix.cxx }}
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v4
|
|
34
|
+
- name: Configure
|
|
35
|
+
run: >
|
|
36
|
+
cmake -S . -B build
|
|
37
|
+
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
|
|
38
|
+
-DMORTON_ENABLE_BMI2=${{ matrix.bmi2 }}
|
|
39
|
+
-DMORTON_BUILD_BINDINGS=OFF
|
|
40
|
+
- name: Build
|
|
41
|
+
run: cmake --build build -j
|
|
42
|
+
- name: Test
|
|
43
|
+
run: ctest --test-dir build --output-on-failure
|
|
44
|
+
|
|
45
|
+
# ---- clang on Linux (separate so the include: above stays simple) ---------
|
|
46
|
+
cpp-linux-clang:
|
|
47
|
+
name: ubuntu / clang / bmi2=${{ matrix.bmi2 }} / ${{ matrix.build_type }}
|
|
48
|
+
runs-on: ubuntu-latest
|
|
49
|
+
strategy:
|
|
50
|
+
fail-fast: false
|
|
51
|
+
matrix:
|
|
52
|
+
bmi2: [ON, OFF]
|
|
53
|
+
build_type: [Debug, Release]
|
|
54
|
+
env:
|
|
55
|
+
CC: clang
|
|
56
|
+
CXX: clang++
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@v4
|
|
59
|
+
- run: >
|
|
60
|
+
cmake -S . -B build -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
|
|
61
|
+
-DMORTON_ENABLE_BMI2=${{ matrix.bmi2 }} -DMORTON_BUILD_BINDINGS=OFF
|
|
62
|
+
- run: cmake --build build -j
|
|
63
|
+
- run: ctest --test-dir build --output-on-failure
|
|
64
|
+
|
|
65
|
+
# ---- AVX-512 + runtime-dispatch validation via Intel SDE ------------------
|
|
66
|
+
# The CI runners have no AVX-512, so we run the test binaries under Intel SDE,
|
|
67
|
+
# a userspace functional emulator. -skx emulates Skylake-X (AVX-512), so the
|
|
68
|
+
# AVX-512 batch kernels in morton/simd.hpp actually execute and are checked
|
|
69
|
+
# bit-for-bit against the scalar reference. The runtime-dispatch build (no
|
|
70
|
+
# -mbmi2) is then exercised across -snb (no BMI2 -> software), -hsw (BMI2,
|
|
71
|
+
# no AVX-512 -> PDEP) and -skx (BMI2 + AVX-512).
|
|
72
|
+
cpp-avx512-sde:
|
|
73
|
+
name: ubuntu / gcc / AVX-512 + dispatch via Intel SDE
|
|
74
|
+
runs-on: ubuntu-latest
|
|
75
|
+
# Intel rotates the SDE download URL/hash periodically; this validates the AVX-512 batch path
|
|
76
|
+
# under emulation but must not gate the build when the external download moves. Update the url +
|
|
77
|
+
# sha256 below when it 404s. (The scalar reference path is fully covered by the cpp jobs above.)
|
|
78
|
+
continue-on-error: true
|
|
79
|
+
steps:
|
|
80
|
+
- uses: actions/checkout@v4
|
|
81
|
+
- name: Install Intel SDE
|
|
82
|
+
run: |
|
|
83
|
+
set -euo pipefail
|
|
84
|
+
url="https://downloadmirror.intel.com/915934/sde-external-10.8.0-2026-03-15-lin.tar.xz"
|
|
85
|
+
curl -sSL -o sde.tar.xz "$url"
|
|
86
|
+
echo "50b320cd226acef7a491f5b321fc1be3c3c7984f9e27a456e64894b5b0979dd3 sde.tar.xz" | sha256sum -c -
|
|
87
|
+
mkdir -p "$HOME/sde" && tar -xJf sde.tar.xz -C "$HOME/sde" --strip-components=1
|
|
88
|
+
echo "$HOME/sde" >> "$GITHUB_PATH"
|
|
89
|
+
- name: Build (default, BMI2 on; AVX-512 kernels compiled via target attribute)
|
|
90
|
+
run: |
|
|
91
|
+
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DMORTON_BUILD_BINDINGS=OFF
|
|
92
|
+
cmake --build build -j
|
|
93
|
+
- name: Tests under SDE Skylake-X (AVX-512 batch path executes)
|
|
94
|
+
run: sde64 -skx -- ./build/tests/morton_tests
|
|
95
|
+
- name: Build runtime-dispatch variant (no -mbmi2)
|
|
96
|
+
run: |
|
|
97
|
+
cmake -S . -B build_rt -DCMAKE_BUILD_TYPE=Release \
|
|
98
|
+
-DMORTON_ENABLE_BMI2=OFF -DMORTON_ENABLE_RUNTIME_DISPATCH=ON \
|
|
99
|
+
-DMORTON_BUILD_BINDINGS=OFF
|
|
100
|
+
cmake --build build_rt -j
|
|
101
|
+
- name: Runtime-dispatch tests across emulated CPUs
|
|
102
|
+
run: |
|
|
103
|
+
sde64 -snb -- ./build_rt/tests/morton_tests # Sandy Bridge: no BMI2/AVX-512 -> software
|
|
104
|
+
sde64 -hsw -- ./build_rt/tests/morton_tests # Haswell: BMI2, no AVX-512 -> PDEP
|
|
105
|
+
sde64 -skx -- ./build_rt/tests/morton_tests # Skylake-X: BMI2 + AVX-512
|
|
106
|
+
|
|
107
|
+
# ---- C++ tests on Windows / MSVC ------------------------------------------
|
|
108
|
+
cpp-msvc:
|
|
109
|
+
name: windows / msvc / ${{ matrix.build_type }}
|
|
110
|
+
runs-on: windows-latest
|
|
111
|
+
strategy:
|
|
112
|
+
fail-fast: false
|
|
113
|
+
matrix:
|
|
114
|
+
build_type: [Debug, Release]
|
|
115
|
+
steps:
|
|
116
|
+
- uses: actions/checkout@v4
|
|
117
|
+
# MSVC has no __int128 and does not define __BMI2__, so the portable
|
|
118
|
+
# software path is exercised here; CMake only adds -mbmi2 if supported.
|
|
119
|
+
- run: cmake -S . -B build -DMORTON_BUILD_BINDINGS=OFF
|
|
120
|
+
- run: cmake --build build --config ${{ matrix.build_type }}
|
|
121
|
+
- run: ctest --test-dir build -C ${{ matrix.build_type }} --output-on-failure
|
|
122
|
+
|
|
123
|
+
# ---- Python wheel build + tests across versions ---------------------------
|
|
124
|
+
python:
|
|
125
|
+
name: python ${{ matrix.python }} (${{ matrix.os }})
|
|
126
|
+
runs-on: ${{ matrix.os }}
|
|
127
|
+
strategy:
|
|
128
|
+
fail-fast: false
|
|
129
|
+
matrix:
|
|
130
|
+
os: [ubuntu-latest, macos-latest]
|
|
131
|
+
python: ["3.9", "3.11", "3.13"]
|
|
132
|
+
steps:
|
|
133
|
+
- uses: actions/checkout@v4
|
|
134
|
+
- uses: actions/setup-python@v5
|
|
135
|
+
with:
|
|
136
|
+
python-version: ${{ matrix.python }}
|
|
137
|
+
- name: Install package (builds the extension via scikit-build-core)
|
|
138
|
+
run: pip install .
|
|
139
|
+
- name: Test (from a clean dir, against the installed package)
|
|
140
|
+
run: |
|
|
141
|
+
pip install pytest numpy
|
|
142
|
+
cd "${{ runner.temp }}"
|
|
143
|
+
python -m pytest "${{ github.workspace }}/bindings/python/tests" -q
|
|
144
|
+
|
|
145
|
+
# ---- Doxygen build (docs must generate without warnings) ------------------
|
|
146
|
+
docs:
|
|
147
|
+
runs-on: ubuntu-latest
|
|
148
|
+
steps:
|
|
149
|
+
- uses: actions/checkout@v4
|
|
150
|
+
- run: sudo apt-get update && sudo apt-get install -y doxygen
|
|
151
|
+
- run: doxygen docs/Doxyfile
|
|
152
|
+
- uses: actions/upload-artifact@v4
|
|
153
|
+
with:
|
|
154
|
+
name: api-docs
|
|
155
|
+
path: docs/doxygen/html
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: Documentation
|
|
2
|
+
|
|
3
|
+
# Build the Doxygen API docs (header-only C++17 in include/morton/) and publish them to GitHub Pages.
|
|
4
|
+
# The CI workflow (ci.yml) also builds the docs as a "must generate" check on every push/PR; THIS
|
|
5
|
+
# workflow additionally DEPLOYS them to Pages on pushes to main. Requires Pages to be enabled for the
|
|
6
|
+
# repository with "Source: GitHub Actions" (Settings -> Pages). Can also be triggered manually.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
branches: [main]
|
|
11
|
+
paths:
|
|
12
|
+
- 'include/**'
|
|
13
|
+
- 'docs/**'
|
|
14
|
+
- 'README.md'
|
|
15
|
+
- '.github/workflows/docs.yml'
|
|
16
|
+
workflow_dispatch:
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
pages: write
|
|
21
|
+
id-token: write
|
|
22
|
+
|
|
23
|
+
concurrency:
|
|
24
|
+
group: pages
|
|
25
|
+
cancel-in-progress: true
|
|
26
|
+
|
|
27
|
+
jobs:
|
|
28
|
+
build:
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@v4
|
|
32
|
+
- name: Install Doxygen + Graphviz
|
|
33
|
+
run: sudo apt-get update && sudo apt-get install -y doxygen graphviz
|
|
34
|
+
- name: Build documentation
|
|
35
|
+
run: doxygen docs/Doxyfile
|
|
36
|
+
- name: Upload Pages artifact
|
|
37
|
+
uses: actions/upload-pages-artifact@v3
|
|
38
|
+
with:
|
|
39
|
+
path: docs/doxygen/html
|
|
40
|
+
|
|
41
|
+
deploy:
|
|
42
|
+
needs: build
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
environment:
|
|
45
|
+
name: github-pages
|
|
46
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
47
|
+
steps:
|
|
48
|
+
- name: Deploy to GitHub Pages
|
|
49
|
+
id: deployment
|
|
50
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Quality
|
|
2
|
+
|
|
3
|
+
# Lightweight, non-breaking code-quality gates. The Python job hard-fails on *critical* errors only
|
|
4
|
+
# (syntax errors, undefined names, bad string formatting / comparisons — the classic stop-the-build
|
|
5
|
+
# set), so it catches real bugs without drowning research scripts in style nits.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
branches: [main, "**"]
|
|
10
|
+
pull_request:
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
python-lint:
|
|
15
|
+
name: ruff (critical errors)
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
- uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.12"
|
|
22
|
+
- run: pip install ruff
|
|
23
|
+
- name: Ruff critical-error check
|
|
24
|
+
run: |
|
|
25
|
+
ruff check . --select E9,F63,F7,F82 \
|
|
26
|
+
--exclude ".venv,venv,build,build_*,__pycache__,_deps,extern,legacy,notebooks"
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Build sdist + binary wheels and publish to PyPI on a version tag.
|
|
4
|
+
# Uses PyPI Trusted Publishing (OIDC) - configure the publisher on PyPI first;
|
|
5
|
+
# no API token secret is needed.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
tags: ["v*"]
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
sdist:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.12"
|
|
20
|
+
- run: pip install build
|
|
21
|
+
- run: python -m build --sdist
|
|
22
|
+
- uses: actions/upload-artifact@v4
|
|
23
|
+
with:
|
|
24
|
+
name: sdist
|
|
25
|
+
path: dist/*.tar.gz
|
|
26
|
+
|
|
27
|
+
wheels:
|
|
28
|
+
name: wheels on ${{ matrix.os }}
|
|
29
|
+
runs-on: ${{ matrix.os }}
|
|
30
|
+
strategy:
|
|
31
|
+
fail-fast: false
|
|
32
|
+
matrix:
|
|
33
|
+
os: [ubuntu-latest, windows-latest, macos-14]
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v4
|
|
36
|
+
- name: Build wheels
|
|
37
|
+
uses: pypa/cibuildwheel@v2.21
|
|
38
|
+
- uses: actions/upload-artifact@v4
|
|
39
|
+
with:
|
|
40
|
+
name: wheels-${{ matrix.os }}
|
|
41
|
+
path: wheelhouse/*.whl
|
|
42
|
+
|
|
43
|
+
publish:
|
|
44
|
+
needs: [sdist, wheels]
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
47
|
+
environment: pypi
|
|
48
|
+
permissions:
|
|
49
|
+
id-token: write # required for trusted publishing
|
|
50
|
+
steps:
|
|
51
|
+
- uses: actions/download-artifact@v4
|
|
52
|
+
with:
|
|
53
|
+
path: dist
|
|
54
|
+
merge-multiple: true
|
|
55
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
build*/
|
|
2
|
+
*.o
|
|
3
|
+
*.so
|
|
4
|
+
*.dylib
|
|
5
|
+
*.dll
|
|
6
|
+
__pycache__/
|
|
7
|
+
*.pyc
|
|
8
|
+
.pytest_cache/
|
|
9
|
+
|
|
10
|
+
# generated docs
|
|
11
|
+
/docs/doxygen/
|
|
12
|
+
|
|
13
|
+
# built ctypes lib + py artifacts
|
|
14
|
+
bindings/python/peclet/morton/libmortonarith_c*
|
|
15
|
+
__pycache__/
|
|
16
|
+
*.pyc
|
|
17
|
+
.pytest_cache/
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## What this is
|
|
6
|
+
|
|
7
|
+
A header-only **C++17** library for Morton (Z-order) codes whose distinguishing feature is **arithmetic directly in Morton space** — incrementing/adding along a single axis, neighbour finding, and Z-order stepping without the usual `decode → modify → re-encode` round trip. The original prototype (an arbitrary-width `BitArray`, a wide-code `Morton`, and an octree) lives in `legacy/`; the new fast core supersedes it for codes that fit in 64 bits.
|
|
8
|
+
|
|
9
|
+
Read `docs/EVALUATION.md` for the honest assessment of what this contributes versus libmorton/morton-nd, and `docs/ROADMAP.md` for the plan.
|
|
10
|
+
|
|
11
|
+
## Build / test / benchmark
|
|
12
|
+
|
|
13
|
+
`DEVELOPMENT.md` is the canonical fresh-machine setup (prerequisites, ISA/platform notes, the full CUDA-via-clang toolkit-assembly recipe); the commands below are the day-to-day subset.
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
|
17
|
+
cmake --build build -j
|
|
18
|
+
ctest --test-dir build --output-on-failure # or ./build/tests/morton_tests
|
|
19
|
+
./build/benchmarks/morton_bench # vs libmorton
|
|
20
|
+
./build/benchmarks/morton_bench_batch # SIMD/batch (cache vs out-of-cache)
|
|
21
|
+
cmake --build build --target docs # Doxygen -> docs/doxygen/html
|
|
22
|
+
|
|
23
|
+
# software (non-BMI2) path — must also pass:
|
|
24
|
+
cmake -S . -B build_nobmi2 -DMORTON_ENABLE_BMI2=OFF && cmake --build build_nobmi2 -j
|
|
25
|
+
|
|
26
|
+
# runtime-dispatch path (single portable binary, no -mbmi2, uses PDEP/AVX-512
|
|
27
|
+
# when the CPU has them) — what the wheels build:
|
|
28
|
+
cmake -S . -B build_rt -DMORTON_ENABLE_BMI2=OFF -DMORTON_ENABLE_RUNTIME_DISPATCH=ON && cmake --build build_rt -j
|
|
29
|
+
|
|
30
|
+
# AVX-512 has no hardware on most dev machines / CI; validate it under Intel SDE
|
|
31
|
+
# (userspace emulator, runs on AMD too). -skx => AVX-512 batch path executes:
|
|
32
|
+
sde64 -skx -- ./build/tests/morton_tests
|
|
33
|
+
# runtime-dispatch build across emulated CPUs (BMI2 present/absent):
|
|
34
|
+
sde64 -snb -- ./build_rt/tests/morton_tests # no BMI2/AVX-512 -> software fallback
|
|
35
|
+
sde64 -hsw -- ./build_rt/tests/morton_tests # BMI2, no AVX-512 -> PDEP path
|
|
36
|
+
sde64 -skx -- ./build_rt/tests/morton_tests # BMI2 + AVX-512
|
|
37
|
+
|
|
38
|
+
# portable Kokkos GPU backend (opt-in; needs a Kokkos prefix on CMAKE_PREFIX_PATH
|
|
39
|
+
# from ../tools/bootstrap_deps.sh <nvidia-cuda|host-openmp|lumi-hip>):
|
|
40
|
+
cmake -S . -B build_kokkos -DMORTON_ENABLE_KOKKOS=ON \
|
|
41
|
+
-DCMAKE_PREFIX_PATH="$PWD/../extern/install/host-openmp" && cmake --build build_kokkos -j
|
|
42
|
+
ctest --test-dir build_kokkos -R morton_kokkos_tests --output-on-failure
|
|
43
|
+
|
|
44
|
+
# Python: proper wheel via scikit-build-core (pip install . from repo root)
|
|
45
|
+
pip install . # builds extension, bundles .so
|
|
46
|
+
python -m pytest bindings/python/tests -q
|
|
47
|
+
# or dev loop without installing:
|
|
48
|
+
cmake --build build --target mortonarith_c # drops .so into bindings/python/peclet/morton/
|
|
49
|
+
PYTHONPATH=bindings/python python3 -m pytest bindings/python/tests -q
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Note: the wheel build is driven by the root `pyproject.toml` → `MORTON_WHEEL=ON` in CMakeLists.txt, which builds only the binding and `return()`s early. Don't remove that early return or the wheel will also try to build tests/benchmarks.
|
|
53
|
+
|
|
54
|
+
A single doctest case can be run with `./build/tests/morton_tests --test-case="<name>"` (doctest filters, e.g. `--subcase=...`, `--list-test-cases`).
|
|
55
|
+
|
|
56
|
+
## Architecture (new core)
|
|
57
|
+
|
|
58
|
+
Header dependency order: `morton.hpp` ← {`iterate.hpp`, `simd.hpp` ← `batch.hpp`}. (The octree was split
|
|
59
|
+
out into the sibling `octree/` subproject — see below — and is no longer a core header.)
|
|
60
|
+
|
|
61
|
+
### `morton/morton.hpp` — `Morton<unsigned Dim, unsigned Bits>`
|
|
62
|
+
|
|
63
|
+
Interleaves `Dim` coordinates of `Bits` bits each. `Dim*Bits <= 64` uses a built-in `code_type`; **65–128 bits use `__uint128_t`** (guarded by `MORTON_HAS_INT128` / `__SIZEOF_INT128__`), so `Morton3D32` (96-bit) and `Morton2D64` (128-bit) work. Key design points:
|
|
64
|
+
|
|
65
|
+
- **Encode/decode** go through `deposit`/`extract`. For `code_bits <= 64` they use BMI2 `_pdep_u64`/`_pext_u64` under `#if defined(__BMI2__)`, else a software fallback (`detail::spread_sw`/`compact_sw`). For `code_bits > 64` the software path is always used (PDEP is 64-bit only). Paths are cross-checked in tests; the BMI2=OFF build verifies the fallback emits no pdep/pext.
|
|
66
|
+
- **Runtime dispatch** (`MORTON_ENABLE_RUNTIME_DISPATCH`, opt-in via the CMake option / compile define; gated to `MORTON_X86_RUNTIME_DISPATCH` on x86-64 GCC/Clang when `-mbmi2` is *not* set): a third `deposit`/`extract` branch calls `detail::pdep_u64_hw`/`pext_u64_hw` — `__attribute__((target("bmi2")))` helpers, so PDEP is emitted without a global `-mbmi2` — guarded by the cached `detail::cpu_has_bmi2()` (`__builtin_cpu_supports`). This yields one portable binary that's BMI2-fast at runtime. **Don't enable it by default for the plain BMI2=OFF build** — that build is contractually pdep-free (a test greps for it). It self-disables under `-mbmi2`/CUDA/non-x86. `MORTON_X86` / `cpu_has_bmi2`/`cpu_has_avx2`/`cpu_has_avx512f` live in `detail` and are shared with the SIMD path.
|
|
67
|
+
- **`constexpr`**: `deposit`/`extract`/`encode`/`decode`/arithmetic are `constexpr`. They call the BMI2 intrinsic only when `!detail::is_consteval()` (which uses `__builtin_is_constant_evaluated()`, available at C++17 on GCC/Clang); in constant evaluation the software path runs. Don't "simplify" by removing the `is_consteval()` guard — the intrinsics aren't constexpr.
|
|
68
|
+
- **The headline arithmetic** (`add`/`sub`/`inc`/`dec`/`neighbor`, O(1), branchless) operates on one axis' interleaved bits: to add to axis `d`, fill non-axis bits with 1s (`code | ~M`) so carries ripple across the gaps, add the dilated increment, keep only axis `d` (`& M`), OR back the others. **Wraps mod `2^Bits` per axis.** `add_sat`/`sub_sat`/`try_add`/`try_sub` are the non-wrapping variants.
|
|
69
|
+
- **Neighbour/hierarchy helpers**: `face_neighbors()` (2·Dim, von Neumann), `all_neighbors()` (`3^Dim-1`, Moore), `ancestor(level)`/`child(level,oct)`/`child_index(level)` for octree navigation.
|
|
70
|
+
- `field_mask`/`coord_max` use `sizeof(T)*CHAR_BIT` (not `numeric_limits::digits`, which isn't specialised for `__int128` under strict `-std=c++17`) to avoid `1<<width` UB. Per-axis masks are an `inline static constexpr std::array axis_masks_` (constexpr-usable *and* fast at runtime).
|
|
71
|
+
|
|
72
|
+
### `morton/iterate.hpp` — region traversal + range search
|
|
73
|
+
|
|
74
|
+
- `for_each_in_box` — row-major (axis 0 fastest) odometer of O(1) `inc`/`set`; never re-encodes the full tuple. **Profiling note:** for *dense* sweeps, per-cell re-encoding is faster (independent PDEPs pipeline; the arithmetic walk is a serial dependency chain). Its value is convenience + the Z-order variant.
|
|
75
|
+
- `for_each_in_box_zorder` — increasing-code order via `detail::litmax_bigmin` (Tropf-Herzog). Also exposes `bigmin_in_box` / `litmax_in_box` for callers driving their own range scans. Validated exhaustively vs brute force.
|
|
76
|
+
|
|
77
|
+
### `morton/batch.hpp` — vectorised bulk ops
|
|
78
|
+
|
|
79
|
+
`batch::add/sub/step/encode2/encode3/decode2/decode3` over arrays. The masked-add loop auto-vectorises (AVX2 `vpaddq`/`vpand`/`vpor`); ~1.7× over scalar when cache-resident, memory-bound parity otherwise (`benchmarks/bench_batch.cpp`). On x86-64 GCC/Clang (`MORTON_X86`) each function **runtime-dispatches** to the explicit AVX-512 kernels in `simd.hpp` when `detail::cpu_has_avx512f()` and the code is 64-bit — transparently, with bit-for-bit identical results — else it falls through to this scalar loop.
|
|
80
|
+
|
|
81
|
+
### `morton/simd.hpp` — explicit AVX-512 batch kernels
|
|
82
|
+
|
|
83
|
+
Hand-written AVX-512 "magic-bits" spread/compact (`detail::avx512::{encode2,decode2,encode3,decode3,add64,sub64}`), 8 codes per iteration, with a scalar tail (so `n` need not be a multiple of 8). Each kernel is `__attribute__((target("avx512f")))`, so the TU needs **no** global `-mavx512f` and the rest of the binary stays portable; they only run when `cpu_has_avx512f()` is true. Coverage is the 64-bit-code, 32-bit-coord layouts: `encode/decode` for `(2,32)` and `(3,21)`, and `add/sub` for any 64-bit code (`(2,32)`,`(3,21)`,`(3,16)`); other layouts use the scalar path. **Validate changes here under Intel SDE** (`sde64 -skx`) — there's usually no AVX-512 hardware locally, and the tests compare the SIMD output against the scalar reference exhaustively.
|
|
84
|
+
|
|
85
|
+
### `morton/wide_uint.hpp` — codes wider than 128 bits
|
|
86
|
+
|
|
87
|
+
`detail::wide_uint<W>` is a minimal fixed-width (`W` × `u64`, little-endian) unsigned providing exactly the operators `Morton` uses (`+ - & | ^ ~ << >>`, comparisons, conversions to `u64`/`__int128`). `uint_for` selects it automatically when `Dim*Bits` exceeds the builtin width (64, or 128 with `__int128`). Cap is `MORTON_MAX_BITS` (default 256). The Morton class body is unchanged — it's all operators — so 192-bit (`Morton<3,64>`) and 256-bit (`Morton<2,128>`) "just work". Don't tune `wide_uint` for speed unless it becomes a hot path; it's deliberately simple.
|
|
88
|
+
|
|
89
|
+
### `include/morton/kokkos.hpp` — portable Kokkos GPU backend (shares the core via `MORTON_HD`)
|
|
90
|
+
|
|
91
|
+
The core's functions are prefixed with `MORTON_HD`. It now resolves to **`KOKKOS_FUNCTION`** when `MORTON_ENABLE_KOKKOS` is set and Kokkos is in the translation unit (so device/host attributes track whichever Kokkos backend — CUDA/HIP/OpenMP/Serial — is active), and falls back to `__host__ __device__` under `__CUDACC__`/`__HIPCC__`, and to nothing for an ordinary host build (so the CPU library is byte-for-byte unchanged). This lets the Kokkos kernels call the **same** `Morton<Dim,Bits>` code — no second implementation. Two gotchas baked into the core (still required under the Kokkos CUDA/HIP device pass):
|
|
92
|
+
- `deposit`/`extract` guard PDEP/PEXT with `#if defined(__BMI2__) && !defined(__CUDA_ARCH__)` — never emit the x86 intrinsic in device code, even when the host is compiled `-mbmi2`. Don't drop the `!defined(__CUDA_ARCH__)`.
|
|
93
|
+
- `axis_mask(d)` computes the mask under `__CUDA_ARCH__` instead of reading the host `static constexpr axis_masks_` array (can't reference a host static from device).
|
|
94
|
+
|
|
95
|
+
`morton::kokkos` offers `Kokkos::View`-based bulk ops — `encode2/3`, `decode2/3`, per-axis `add`/`sub`/`step` (execution space deduced from the View) — plus `*_host` raw-pointer convenience wrappers (stage to device Views, run, copy back). `tests/kokkos/test_kokkos.cpp` validates device output bit-for-bit against the scalar `Morton<>` reference for all four binding layouts `(2,32) (2,16) (3,21) (3,16)`; `benchmarks/bench_kokkos.cpp` shows device-resident ~51 GMops/s (CUDA) vs PCIe-bound host round-trip.
|
|
96
|
+
|
|
97
|
+
Build: opt-in with `-DMORTON_ENABLE_KOKKOS=ON` + `find_package(Kokkos CONFIG)` against the suite's bootstrapped prefix (`extern/install/<backend>` from `tools/bootstrap_deps.sh`) on `CMAKE_PREFIX_PATH`, exactly like `flow`/`dem`. Device sources stay plain `.cpp` — Kokkos 5.x routes them through the launch compiler (see `../cmake/SuiteKokkos.cmake`). The plain (non-Kokkos) build never touches Kokkos and is unchanged. **The raw-CUDA backend was retired** (was `cuda/`, `morton::cuda`); the last raw-CUDA tree is at the `pre-cuda-retirement` git tag.
|
|
98
|
+
|
|
99
|
+
### Octree → sibling `octree/` project
|
|
100
|
+
|
|
101
|
+
The octree is **no longer part of this library**. It moved to `octree/` (`morton_octree::Octree`, `octree/include/morton_octree/octree.hpp`), a separate project that depends on `morton::morton`. See `octree/PLAN.md`. `legacy/octree.hpp` remains the original prototype/reference.
|
|
102
|
+
|
|
103
|
+
## Packaging / distribution
|
|
104
|
+
|
|
105
|
+
- **CMake**: `install` exports a package config (`cmake/morton-config.cmake.in` → `find_package(morton CONFIG)` → `morton::morton`). The `-mbmi2` interface flag is guarded by `$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>` so it's safe to propagate to consumers.
|
|
106
|
+
- **Conan** `conanfile.py`, **vcpkg** `packaging/vcpkg/morton/` (set REF/SHA512 at release).
|
|
107
|
+
- **Python wheels**: `.github/workflows/release.yml` + cibuildwheel build with `MORTON_ENABLE_BMI2=OFF -DMORTON_ENABLE_RUNTIME_DISPATCH=ON` (via `CMAKE_ARGS`) — no global `-mbmi2` (so no SIGILL on old CPUs) but PDEP/PEXT and the AVX-512 batch kernels still kick in at runtime via `target`-attribute helpers + CPUID. One wheel, portable *and* fast. (On MSVC/non-x86 the dispatch self-disables → software path.) Source `pip install .` stays BMI2-on. The C ABI shim (`bindings/morton_c.cpp`) routes 64-bit-code configs through `batch::` so Python gets the dispatched paths; `(2,16)` (32-bit code) keeps the per-element path.
|
|
108
|
+
|
|
109
|
+
## Conventions / gotchas
|
|
110
|
+
|
|
111
|
+
- Everything is templated on compile-time `Dim` and `Bits`; that is what makes masks/shifts free. Don't add runtime dimension/bit-width to the hot path.
|
|
112
|
+
- The arithmetic advantage is for **scattered/data-dependent neighbour access**, not dense sweeps — keep this framing in docs and benchmarks. Don't market the library as a faster encoder; it is at parity with libmorton on encode/decode.
|
|
113
|
+
- `third_party/` vendors `doctest.h` and `libmorton/` purely for tests/benchmarks; they are not part of the shipped library.
|
|
114
|
+
- Python bindings are deliberately dependency-free: a C ABI shim (`bindings/morton_c.cpp`, `extern "C"`, bulk array functions) + a `ctypes` wrapper. Supported configs are `(2,32) (2,16) (3,21) (3,16)`; adding one means adding a `DEFINE_2D/3D` instantiation *and* an entry in `_CONFIG` in `__init__.py`.
|
|
115
|
+
|
|
116
|
+
## Legacy (`legacy/`)
|
|
117
|
+
|
|
118
|
+
`legacy/octree.hpp` (linear octree over a `std::map<Morton,Cell>`), `legacy/morton.hpp` (CRTP `Morton` over arbitrary-width `BitArrayBase`), `legacy/bitarray.hpp`. These require **C++20** (`<bit>` `std::countr_zero`, fold expressions) and have no build target; the octree visualization notebook is `legacy/octree_visualize.ipynb` (dumps `llx lly urx ury` rows to `temp.dat`, plots with matplotlib). Porting the octree onto the new core is a roadmap item.
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.16)
|
|
2
|
+
project(morton_arithmetic VERSION 0.1.0 LANGUAGES CXX)
|
|
3
|
+
|
|
4
|
+
# ---------------------------------------------------------------------------
|
|
5
|
+
# Header-only interface library
|
|
6
|
+
# ---------------------------------------------------------------------------
|
|
7
|
+
add_library(morton INTERFACE)
|
|
8
|
+
add_library(morton::morton ALIAS morton)
|
|
9
|
+
target_include_directories(morton INTERFACE
|
|
10
|
+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
|
11
|
+
$<INSTALL_INTERFACE:include>)
|
|
12
|
+
target_compile_features(morton INTERFACE cxx_std_17)
|
|
13
|
+
|
|
14
|
+
option(MORTON_ENABLE_BMI2 "Use BMI2 PDEP/PEXT for encode/decode" ON)
|
|
15
|
+
include(CheckCXXCompilerFlag)
|
|
16
|
+
check_cxx_compiler_flag("-mbmi2" MORTON_HAS_MBMI2)
|
|
17
|
+
if(MORTON_ENABLE_BMI2 AND MORTON_HAS_MBMI2)
|
|
18
|
+
# Only GCC/Clang understand -mbmi2; guard so the flag is safe to propagate
|
|
19
|
+
# to consumers of the installed package (MSVC/other compilers ignore it).
|
|
20
|
+
target_compile_options(morton INTERFACE
|
|
21
|
+
$<$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>:-mbmi2>)
|
|
22
|
+
endif()
|
|
23
|
+
|
|
24
|
+
# Single-binary runtime ISA dispatch (x86-64 GCC/Clang). Builds *without*
|
|
25
|
+
# -mbmi2 but still uses PDEP/PEXT when the running CPU has BMI2 (software path
|
|
26
|
+
# otherwise), via per-function `target` attributes. Intended to be paired with
|
|
27
|
+
# MORTON_ENABLE_BMI2=OFF (it self-disables when -mbmi2 is on). The AVX-512 batch
|
|
28
|
+
# kernels are always runtime-dispatched and need no option. This lets a portable
|
|
29
|
+
# distributable binary (e.g. a wheel) keep the BMI2/AVX-512 fast paths.
|
|
30
|
+
option(MORTON_ENABLE_RUNTIME_DISPATCH
|
|
31
|
+
"Single-binary runtime BMI2 dispatch (build without -mbmi2)" OFF)
|
|
32
|
+
if(MORTON_ENABLE_RUNTIME_DISPATCH)
|
|
33
|
+
target_compile_definitions(morton INTERFACE MORTON_ENABLE_RUNTIME_DISPATCH=1)
|
|
34
|
+
endif()
|
|
35
|
+
|
|
36
|
+
# Portable Kokkos backend (include/morton/kokkos.hpp). Opt-in: the plain build
|
|
37
|
+
# (and the wheels) never touch Kokkos and stay bit-identical. When ON, Kokkos is
|
|
38
|
+
# found via find_package(CONFIG) against the suite's bootstrapped install prefix
|
|
39
|
+
# (extern/install/<backend>, from tools/bootstrap_deps.sh) or a cluster module --
|
|
40
|
+
# the same single mechanism the rest of the suite uses. The backend (CUDA / HIP /
|
|
41
|
+
# OpenMP / Serial) and architecture come from that Kokkos build, not from here.
|
|
42
|
+
option(MORTON_ENABLE_KOKKOS "Build the portable Kokkos backend (and its tests/bench)" OFF)
|
|
43
|
+
if(MORTON_ENABLE_KOKKOS)
|
|
44
|
+
find_package(Kokkos CONFIG REQUIRED)
|
|
45
|
+
message(STATUS "morton: Kokkos ${Kokkos_VERSION} (backends: ${Kokkos_DEVICES})")
|
|
46
|
+
target_compile_definitions(morton INTERFACE MORTON_ENABLE_KOKKOS=1)
|
|
47
|
+
target_link_libraries(morton INTERFACE Kokkos::kokkos)
|
|
48
|
+
endif()
|
|
49
|
+
|
|
50
|
+
# Wheel mode (driven by scikit-build-core via the root pyproject.toml): build
|
|
51
|
+
# only the Python extension and install it into the package directory.
|
|
52
|
+
option(MORTON_WHEEL "Build only the Python extension for a wheel" OFF)
|
|
53
|
+
if(MORTON_WHEEL)
|
|
54
|
+
add_subdirectory(bindings)
|
|
55
|
+
# LIBRARY = .so/.dylib (Linux/macOS); RUNTIME = .dll (Windows — the actual loadable artifact for ctypes)
|
|
56
|
+
install(TARGETS mortonarith_c
|
|
57
|
+
LIBRARY DESTINATION peclet/morton
|
|
58
|
+
RUNTIME DESTINATION peclet/morton)
|
|
59
|
+
return()
|
|
60
|
+
endif()
|
|
61
|
+
|
|
62
|
+
# Only build the extras when this is the top-level project.
|
|
63
|
+
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
|
64
|
+
option(MORTON_BUILD_TESTS "Build the test suite" ON)
|
|
65
|
+
option(MORTON_BUILD_BENCHMARKS "Build the benchmarks" ON)
|
|
66
|
+
option(MORTON_BUILD_BINDINGS "Build the C ABI shared library for Python" ON)
|
|
67
|
+
|
|
68
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
69
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
70
|
+
if(NOT CMAKE_BUILD_TYPE)
|
|
71
|
+
set(CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE)
|
|
72
|
+
endif()
|
|
73
|
+
|
|
74
|
+
if(MORTON_BUILD_TESTS)
|
|
75
|
+
enable_testing()
|
|
76
|
+
add_subdirectory(tests)
|
|
77
|
+
if(MORTON_ENABLE_KOKKOS)
|
|
78
|
+
add_subdirectory(tests/kokkos)
|
|
79
|
+
endif()
|
|
80
|
+
endif()
|
|
81
|
+
if(MORTON_BUILD_BENCHMARKS)
|
|
82
|
+
add_subdirectory(benchmarks)
|
|
83
|
+
endif()
|
|
84
|
+
if(MORTON_BUILD_BINDINGS)
|
|
85
|
+
add_subdirectory(bindings)
|
|
86
|
+
endif()
|
|
87
|
+
|
|
88
|
+
# `cmake --build build --target docs` (if Doxygen is installed)
|
|
89
|
+
find_package(Doxygen)
|
|
90
|
+
if(DOXYGEN_FOUND)
|
|
91
|
+
add_custom_target(docs
|
|
92
|
+
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_SOURCE_DIR}/docs/Doxyfile
|
|
93
|
+
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
94
|
+
COMMENT "Generating API documentation with Doxygen"
|
|
95
|
+
VERBATIM)
|
|
96
|
+
endif()
|
|
97
|
+
endif()
|
|
98
|
+
|
|
99
|
+
# ---------------------------------------------------------------------------
|
|
100
|
+
# Install + CMake package config so consumers can `find_package(morton)`
|
|
101
|
+
# ---------------------------------------------------------------------------
|
|
102
|
+
include(GNUInstallDirs)
|
|
103
|
+
include(CMakePackageConfigHelpers)
|
|
104
|
+
|
|
105
|
+
set(MORTON_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/morton)
|
|
106
|
+
|
|
107
|
+
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
|
108
|
+
install(TARGETS morton EXPORT mortonTargets)
|
|
109
|
+
install(EXPORT mortonTargets
|
|
110
|
+
FILE morton-targets.cmake
|
|
111
|
+
NAMESPACE morton::
|
|
112
|
+
DESTINATION ${MORTON_CMAKE_DIR})
|
|
113
|
+
|
|
114
|
+
configure_package_config_file(
|
|
115
|
+
${CMAKE_CURRENT_SOURCE_DIR}/cmake/morton-config.cmake.in
|
|
116
|
+
${CMAKE_CURRENT_BINARY_DIR}/morton-config.cmake
|
|
117
|
+
INSTALL_DESTINATION ${MORTON_CMAKE_DIR})
|
|
118
|
+
write_basic_package_version_file(
|
|
119
|
+
${CMAKE_CURRENT_BINARY_DIR}/morton-config-version.cmake
|
|
120
|
+
VERSION ${PROJECT_VERSION}
|
|
121
|
+
COMPATIBILITY SameMajorVersion
|
|
122
|
+
ARCH_INDEPENDENT)
|
|
123
|
+
install(FILES
|
|
124
|
+
${CMAKE_CURRENT_BINARY_DIR}/morton-config.cmake
|
|
125
|
+
${CMAKE_CURRENT_BINARY_DIR}/morton-config-version.cmake
|
|
126
|
+
DESTINATION ${MORTON_CMAKE_DIR})
|