homapy 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.
- homapy-0.1.0/.clang-format +44 -0
- homapy-0.1.0/.github/workflows/build.yml +43 -0
- homapy-0.1.0/.github/workflows/wheels.yml +221 -0
- homapy-0.1.0/.gitignore +25 -0
- homapy-0.1.0/CMakeLists.txt +320 -0
- homapy-0.1.0/LICENSE +25 -0
- homapy-0.1.0/PKG-INFO +250 -0
- homapy-0.1.0/README.md +214 -0
- homapy-0.1.0/assets/permutation_bottleneck.png +0 -0
- homapy-0.1.0/assets/tetwild_benchmark.png +0 -0
- homapy-0.1.0/assets/thingi10k _benchmark.png +0 -0
- homapy-0.1.0/cmake/recipes/cholmod.cmake +103 -0
- homapy-0.1.0/cmake/recipes/cli11.cmake +28 -0
- homapy-0.1.0/cmake/recipes/cudss.cmake +535 -0
- homapy-0.1.0/cmake/recipes/eigen.cmake +26 -0
- homapy-0.1.0/cmake/recipes/googletest.cmake +13 -0
- homapy-0.1.0/cmake/recipes/libigl.cmake +29 -0
- homapy-0.1.0/cmake/recipes/lloyd_clustering.cmake +13 -0
- homapy-0.1.0/cmake/recipes/metis.cmake +51 -0
- homapy-0.1.0/cmake/recipes/metis_tls_patch.cmake +63 -0
- homapy-0.1.0/cmake/recipes/mkl.cmake +581 -0
- homapy-0.1.0/cmake/recipes/nanobind.cmake +31 -0
- homapy-0.1.0/cmake/recipes/spdlog.cmake +9 -0
- homapy-0.1.0/cmake/recipes/suitesparse.cmake +97 -0
- homapy-0.1.0/data/suitesparse_spd/manifest.csv +1044 -0
- homapy-0.1.0/environment.yml +14 -0
- homapy-0.1.0/examples/CMakeLists.txt +45 -0
- homapy-0.1.0/examples/README.md +28 -0
- homapy-0.1.0/examples/cholmod_example.cpp +139 -0
- homapy-0.1.0/examples/cleanup_mesh.h +106 -0
- homapy-0.1.0/examples/cudss_example.cpp +296 -0
- homapy-0.1.0/examples/matrix_example.cpp +456 -0
- homapy-0.1.0/examples/mkl_example.cpp +141 -0
- homapy-0.1.0/examples/python_solve.py +102 -0
- homapy-0.1.0/examples/util.h +263 -0
- homapy-0.1.0/include/homa/homa.h +46 -0
- homapy-0.1.0/include/homa/matrix_view.h +48 -0
- homapy-0.1.0/include/homa/ordering/amd_order_helper.h +13 -0
- homapy-0.1.0/include/homa/ordering/cpu_ordering_with_patch.h +356 -0
- homapy-0.1.0/include/homa/patcher.h +24 -0
- homapy-0.1.0/include/homa/patching/greedy_patcher.h +22 -0
- homapy-0.1.0/include/homa/patching/lloyd_patcher.h +35 -0
- homapy-0.1.0/include/homa/patching/metis_patcher.h +22 -0
- homapy-0.1.0/include/homa/solvers/CHOLMODSolver.h +74 -0
- homapy-0.1.0/include/homa/solvers/CUDSSSolver.h +87 -0
- homapy-0.1.0/include/homa/solvers/LinSysSolver.h +207 -0
- homapy-0.1.0/include/homa/solvers/MKLSolver.h +81 -0
- homapy-0.1.0/include/homa/solvers/scalar_traits.h +82 -0
- homapy-0.1.0/include/homa/types.h +75 -0
- homapy-0.1.0/include/homa/utils/SPD_cot_matrix.h +128 -0
- homapy-0.1.0/include/homa/utils/check_valid_permutation.h +12 -0
- homapy-0.1.0/include/homa/utils/compress_hessian.h +8 -0
- homapy-0.1.0/include/homa/utils/cuda_error_handler.h +53 -0
- homapy-0.1.0/include/homa/utils/nvtx_helper.h +32 -0
- homapy-0.1.0/include/homa/utils/remove_diagonal.h +14 -0
- homapy-0.1.0/input/meshes/bumpy-cube.obj +59906 -0
- homapy-0.1.0/input/meshes/bunnyhead.obj +4566 -0
- homapy-0.1.0/input/meshes/car.msh +14779 -0
- homapy-0.1.0/input/meshes/cloth.obj +2582 -0
- homapy-0.1.0/input/meshes/cube.obj +36 -0
- homapy-0.1.0/input/meshes/diamond.obj +6 -0
- homapy-0.1.0/input/meshes/dragon.obj +30016 -0
- homapy-0.1.0/input/meshes/el_topo_sphere_1280.obj +1923 -0
- homapy-0.1.0/input/meshes/giraffe.obj +9386 -0
- homapy-0.1.0/input/meshes/giraffe_embedding.obj +13254 -0
- homapy-0.1.0/input/meshes/plane.obj +17 -0
- homapy-0.1.0/input/meshes/plane_5.obj +57 -0
- homapy-0.1.0/input/meshes/sphere1.obj +90 -0
- homapy-0.1.0/input/meshes/sphere3.obj +1156 -0
- homapy-0.1.0/input/meshes/sphere3_patches +0 -0
- homapy-0.1.0/input/meshes/torus.obj +13840 -0
- homapy-0.1.0/input/meshes/torus_patches +0 -0
- homapy-0.1.0/output/.gitkeep +0 -0
- homapy-0.1.0/pyproject.toml +38 -0
- homapy-0.1.0/python/CMakeLists.txt +27 -0
- homapy-0.1.0/python/README.md +66 -0
- homapy-0.1.0/python/homapy/__init__.py +437 -0
- homapy-0.1.0/python/homapy/_dll.py +76 -0
- homapy-0.1.0/python/src/homapy_bindings.cpp +287 -0
- homapy-0.1.0/scripts/download_suitesparse_spd.py +474 -0
- homapy-0.1.0/scripts/examples/run_cholmod_example.sh +24 -0
- homapy-0.1.0/scripts/examples/run_cudss_example.sh +69 -0
- homapy-0.1.0/scripts/examples/run_mkl_example.sh +24 -0
- homapy-0.1.0/scripts/examples/run_spd_benchmark.cmd +80 -0
- homapy-0.1.0/scripts/examples/run_spd_benchmark.sh +85 -0
- homapy-0.1.0/src/ordering/amd_order_helper.cpp +12 -0
- homapy-0.1.0/src/ordering/cpu_ordering_with_patch.cpp +1618 -0
- homapy-0.1.0/src/ordering/homa.cpp +411 -0
- homapy-0.1.0/src/patching/greedy_patcher.cpp +252 -0
- homapy-0.1.0/src/patching/lloyd_patcher.cpp +79 -0
- homapy-0.1.0/src/patching/metis_patcher.cpp +68 -0
- homapy-0.1.0/src/solvers/CHOLMODSolver.cpp +503 -0
- homapy-0.1.0/src/solvers/CUDSSSolver.cu +886 -0
- homapy-0.1.0/src/solvers/LinSysSolver.cpp +215 -0
- homapy-0.1.0/src/solvers/MKLSolver.cpp +397 -0
- homapy-0.1.0/src/utils/check_valid_permutation.cpp +51 -0
- homapy-0.1.0/src/utils/compress_hessian.cpp +56 -0
- homapy-0.1.0/src/utils/remove_diagonal.cpp +80 -0
- homapy-0.1.0/tests/CMakeLists.txt +3 -0
- homapy-0.1.0/tests/ordering/CMakeLists.txt +9 -0
- homapy-0.1.0/tests/ordering/test_patch_ordering_etree.cpp +82 -0
- homapy-0.1.0/tests/python/test_solver_perm_refactor.py +209 -0
- homapy-0.1.0/tests/solvers/CMakeLists.txt +7 -0
- homapy-0.1.0/tests/solvers/test_solver_perm_refactor.cpp +224 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
Language: Cpp
|
|
3
|
+
BasedOnStyle: Chromium
|
|
4
|
+
SortIncludes: Never
|
|
5
|
+
IncludeBlocks: Preserve
|
|
6
|
+
TabWidth: 4
|
|
7
|
+
UseTab: Never
|
|
8
|
+
|
|
9
|
+
AlignConsecutiveAssignments: true
|
|
10
|
+
AllowShortFunctionsOnASingleLine: false
|
|
11
|
+
AllowShortIfStatementsOnASingleLine: false
|
|
12
|
+
AllowShortLoopsOnASingleLine: false
|
|
13
|
+
AlwaysBreakTemplateDeclarations: true
|
|
14
|
+
AlignTrailingComments: true
|
|
15
|
+
BinPackArguments: false
|
|
16
|
+
BinPackParameters: false
|
|
17
|
+
BreakBeforeTernaryOperators: false
|
|
18
|
+
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
|
19
|
+
Cpp11BracedListStyle: true
|
|
20
|
+
IndentCaseLabels: true
|
|
21
|
+
IndentWidth: 4
|
|
22
|
+
IndentWrappedFunctionNames: false
|
|
23
|
+
KeepEmptyLinesAtTheStartOfBlocks: true
|
|
24
|
+
MacroBlockBegin: ''
|
|
25
|
+
MacroBlockEnd: ''
|
|
26
|
+
MaxEmptyLinesToKeep: 2
|
|
27
|
+
NamespaceIndentation: None
|
|
28
|
+
ObjCBlockIndentWidth: 2
|
|
29
|
+
ColumnLimit: 80
|
|
30
|
+
AlignConsecutiveDeclarations: true
|
|
31
|
+
|
|
32
|
+
BreakBeforeBraces: Custom
|
|
33
|
+
BraceWrapping:
|
|
34
|
+
AfterClass: true
|
|
35
|
+
AfterControlStatement: false
|
|
36
|
+
AfterEnum: true
|
|
37
|
+
AfterFunction: true
|
|
38
|
+
AfterNamespace: false
|
|
39
|
+
AfterStruct: true
|
|
40
|
+
AfterUnion: true
|
|
41
|
+
AfterExternBlock: true
|
|
42
|
+
BeforeCatch: false
|
|
43
|
+
BeforeElse: false
|
|
44
|
+
...
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: Build
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
compile:
|
|
11
|
+
name: ${{ matrix.os }} Release
|
|
12
|
+
runs-on: ${{ matrix.os }}
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
os: [ubuntu-22.04, windows-2022]
|
|
17
|
+
|
|
18
|
+
env:
|
|
19
|
+
CMAKE_BUILD_PARALLEL_LEVEL: 2
|
|
20
|
+
CTEST_OUTPUT_ON_FAILURE: 1
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout
|
|
24
|
+
uses: actions/checkout@v4
|
|
25
|
+
|
|
26
|
+
- name: Install CUDA Toolkit
|
|
27
|
+
uses: Jimver/cuda-toolkit@v0.2.35
|
|
28
|
+
with:
|
|
29
|
+
cuda: "12.6.3"
|
|
30
|
+
method: network
|
|
31
|
+
log-file-suffix: ${{ matrix.os }}.txt
|
|
32
|
+
|
|
33
|
+
- name: Show tool versions
|
|
34
|
+
run: cmake --version && nvcc --version
|
|
35
|
+
|
|
36
|
+
- name: Configure
|
|
37
|
+
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DHOMA_BUILD_EXAMPLE=ON -DHOMA_BUILD_TESTS=ON -DHOMA_WITH_CHOLMOD=ON -DHOMA_WITH_MKL=ON -DHOMA_WITH_CUDSS=ON -DHOMA_WITH_CUDA=ON "-DCMAKE_CUDA_ARCHITECTURES=75;80;89;90"
|
|
38
|
+
|
|
39
|
+
- name: Build
|
|
40
|
+
run: cmake --build build --config Release --parallel 2
|
|
41
|
+
|
|
42
|
+
# - name: Test
|
|
43
|
+
# run: ctest --test-dir build -C Release --output-on-failure
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
name: Build wheels
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
tags:
|
|
7
|
+
- "v*"
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
inputs:
|
|
10
|
+
publish:
|
|
11
|
+
description: "Publish target"
|
|
12
|
+
required: true
|
|
13
|
+
type: choice
|
|
14
|
+
default: "none"
|
|
15
|
+
options:
|
|
16
|
+
- none
|
|
17
|
+
- testpypi
|
|
18
|
+
- pypi
|
|
19
|
+
|
|
20
|
+
permissions:
|
|
21
|
+
contents: read
|
|
22
|
+
|
|
23
|
+
env:
|
|
24
|
+
CUDA_VERSION: "12.6.3"
|
|
25
|
+
CUDA_ARCHITECTURES: "75;80;86;89;90"
|
|
26
|
+
|
|
27
|
+
jobs:
|
|
28
|
+
wheels:
|
|
29
|
+
name: Wheels (${{ matrix.os }})
|
|
30
|
+
runs-on: ${{ matrix.os }}
|
|
31
|
+
strategy:
|
|
32
|
+
fail-fast: false
|
|
33
|
+
matrix:
|
|
34
|
+
include:
|
|
35
|
+
- os: ubuntu-22.04
|
|
36
|
+
artifact: homapy-wheels-linux
|
|
37
|
+
- os: windows-2022
|
|
38
|
+
artifact: homapy-wheels-windows
|
|
39
|
+
|
|
40
|
+
steps:
|
|
41
|
+
- uses: actions/checkout@v4
|
|
42
|
+
with:
|
|
43
|
+
persist-credentials: false
|
|
44
|
+
|
|
45
|
+
- uses: actions/setup-python@v5
|
|
46
|
+
with:
|
|
47
|
+
python-version: "3.12"
|
|
48
|
+
|
|
49
|
+
- name: Install CUDA Toolkit on Windows
|
|
50
|
+
if: runner.os == 'Windows'
|
|
51
|
+
uses: Jimver/cuda-toolkit@v0.2.35
|
|
52
|
+
with:
|
|
53
|
+
cuda: ${{ env.CUDA_VERSION }}
|
|
54
|
+
method: network
|
|
55
|
+
|
|
56
|
+
- name: Build wheels
|
|
57
|
+
uses: pypa/cibuildwheel@v2.21.3
|
|
58
|
+
env:
|
|
59
|
+
CIBW_BUILD: "cp39-* cp310-* cp311-* cp312-*"
|
|
60
|
+
CIBW_SKIP: "*-musllinux_*"
|
|
61
|
+
CIBW_ARCHS_LINUX: "x86_64"
|
|
62
|
+
CIBW_ARCHS_WINDOWS: "AMD64"
|
|
63
|
+
CIBW_BUILD_FRONTEND: "build"
|
|
64
|
+
CIBW_CONFIG_SETTINGS: >-
|
|
65
|
+
cmake.define.CMAKE_CUDA_ARCHITECTURES=${{ env.CUDA_ARCHITECTURES }}
|
|
66
|
+
cmake.define.HOMA_BUILD_PYTHON=ON
|
|
67
|
+
cmake.define.HOMA_BUILD_EXAMPLE=OFF
|
|
68
|
+
cmake.define.HOMA_BUILD_TESTS=OFF
|
|
69
|
+
cmake.define.HOMA_WITH_CUDA=ON
|
|
70
|
+
cmake.define.HOMA_WITH_CHOLMOD=ON
|
|
71
|
+
cmake.define.HOMA_WITH_MKL=ON
|
|
72
|
+
cmake.define.HOMA_WITH_CUDSS=ON
|
|
73
|
+
cmake.define.HOMA_WITH_LLOYD_PATCHER=ON
|
|
74
|
+
CIBW_TEST_COMMAND: 'python -c "import homapy"'
|
|
75
|
+
CIBW_TEST_REQUIRES_LINUX: "scipy"
|
|
76
|
+
CIBW_TEST_COMMAND_LINUX: >-
|
|
77
|
+
python -c "import homapy, numpy as np, scipy.sparse as sp; A = sp.diags([-np.ones(3), 4*np.ones(4), -np.ones(3)], [-1, 0, 1], format='csr'); b = np.ones(4); x = homapy.spsolve(A, b, backend='mkl', dtype='float64', reorder=False); assert np.linalg.norm(A @ x - b) < 1e-10"
|
|
78
|
+
CIBW_MANYLINUX_X86_64_IMAGE: "manylinux_2_28"
|
|
79
|
+
CIBW_ENVIRONMENT_LINUX: >-
|
|
80
|
+
PATH=/usr/local/cuda/bin:$PATH
|
|
81
|
+
LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
|
|
82
|
+
CUDA_HOME=/usr/local/cuda
|
|
83
|
+
CUDA_PATH=/usr/local/cuda
|
|
84
|
+
CUDACXX=/usr/local/cuda/bin/nvcc
|
|
85
|
+
CIBW_BEFORE_ALL_LINUX: |
|
|
86
|
+
set -eux
|
|
87
|
+
dnf install -y dnf-plugins-core wget ca-certificates
|
|
88
|
+
dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel8/x86_64/cuda-rhel8.repo
|
|
89
|
+
dnf clean expire-cache
|
|
90
|
+
dnf install -y cuda-toolkit-12-6
|
|
91
|
+
ln -sfn /usr/local/cuda-12.6 /usr/local/cuda
|
|
92
|
+
CIBW_REPAIR_WHEEL_COMMAND_LINUX: >-
|
|
93
|
+
auditwheel repair
|
|
94
|
+
--exclude libcuda.so.1
|
|
95
|
+
--exclude libcudart.so.12
|
|
96
|
+
--exclude libcublas.so.12
|
|
97
|
+
--exclude libcublasLt.so.12
|
|
98
|
+
--exclude libcusolver.so.11
|
|
99
|
+
--exclude libcusparse.so.12
|
|
100
|
+
--exclude libnvJitLink.so.12
|
|
101
|
+
--exclude libnvrtc.so.12
|
|
102
|
+
--exclude libiomp5.so
|
|
103
|
+
--exclude libmkl_rt.so.2
|
|
104
|
+
--exclude libmkl_core.so.2
|
|
105
|
+
--exclude libmkl_intel_lp64.so.2
|
|
106
|
+
--exclude libmkl_intel_thread.so.2
|
|
107
|
+
--exclude libmkl_sequential.so.2
|
|
108
|
+
--exclude libmkl_def.so.2
|
|
109
|
+
--exclude libmkl_avx2.so.2
|
|
110
|
+
--exclude libmkl_avx512.so.2
|
|
111
|
+
--exclude libmkl_mc3.so.2
|
|
112
|
+
-w {dest_dir} {wheel}
|
|
113
|
+
|
|
114
|
+
- name: Inspect Linux wheels
|
|
115
|
+
if: runner.os == 'Linux'
|
|
116
|
+
run: |
|
|
117
|
+
python -m pip install auditwheel
|
|
118
|
+
for wheel in wheelhouse/*.whl; do
|
|
119
|
+
auditwheel show "$wheel"
|
|
120
|
+
done
|
|
121
|
+
|
|
122
|
+
- name: Inspect Windows wheels
|
|
123
|
+
if: runner.os == 'Windows'
|
|
124
|
+
shell: pwsh
|
|
125
|
+
run: |
|
|
126
|
+
python -m pip install delvewheel
|
|
127
|
+
Get-ChildItem wheelhouse\*.whl | ForEach-Object { python -m delvewheel show $_.FullName }
|
|
128
|
+
|
|
129
|
+
- uses: actions/upload-artifact@v4
|
|
130
|
+
with:
|
|
131
|
+
name: ${{ matrix.artifact }}
|
|
132
|
+
path: wheelhouse/*.whl
|
|
133
|
+
if-no-files-found: error
|
|
134
|
+
|
|
135
|
+
sdist:
|
|
136
|
+
name: Source distribution
|
|
137
|
+
runs-on: ubuntu-22.04
|
|
138
|
+
|
|
139
|
+
steps:
|
|
140
|
+
- uses: actions/checkout@v4
|
|
141
|
+
with:
|
|
142
|
+
persist-credentials: false
|
|
143
|
+
|
|
144
|
+
- uses: actions/setup-python@v5
|
|
145
|
+
with:
|
|
146
|
+
python-version: "3.12"
|
|
147
|
+
|
|
148
|
+
- name: Build sdist
|
|
149
|
+
run: |
|
|
150
|
+
python -m pip install build
|
|
151
|
+
python -m build --sdist
|
|
152
|
+
|
|
153
|
+
- uses: actions/upload-artifact@v4
|
|
154
|
+
with:
|
|
155
|
+
name: homapy-sdist
|
|
156
|
+
path: dist/*.tar.gz
|
|
157
|
+
if-no-files-found: error
|
|
158
|
+
|
|
159
|
+
publish:
|
|
160
|
+
name: Publish package
|
|
161
|
+
runs-on: ubuntu-22.04
|
|
162
|
+
needs:
|
|
163
|
+
- wheels
|
|
164
|
+
- sdist
|
|
165
|
+
if: >-
|
|
166
|
+
startsWith(github.ref, 'refs/tags/v') ||
|
|
167
|
+
(github.event_name == 'workflow_dispatch' && github.event.inputs.publish != 'none')
|
|
168
|
+
permissions:
|
|
169
|
+
contents: read
|
|
170
|
+
id-token: write
|
|
171
|
+
environment: pypi
|
|
172
|
+
|
|
173
|
+
steps:
|
|
174
|
+
- uses: actions/checkout@v4
|
|
175
|
+
with:
|
|
176
|
+
persist-credentials: false
|
|
177
|
+
|
|
178
|
+
- uses: actions/setup-python@v5
|
|
179
|
+
with:
|
|
180
|
+
python-version: "3.12"
|
|
181
|
+
|
|
182
|
+
- name: Check tag matches pyproject version
|
|
183
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
184
|
+
shell: bash
|
|
185
|
+
run: |
|
|
186
|
+
python - <<'PY'
|
|
187
|
+
import os
|
|
188
|
+
import sys
|
|
189
|
+
import tomllib
|
|
190
|
+
|
|
191
|
+
with open("pyproject.toml", "rb") as f:
|
|
192
|
+
version = tomllib.load(f)["project"]["version"]
|
|
193
|
+
|
|
194
|
+
tag = os.environ["GITHUB_REF_NAME"]
|
|
195
|
+
expected = f"v{version}"
|
|
196
|
+
if tag != expected:
|
|
197
|
+
print(f"Tag {tag!r} does not match pyproject.toml version {version!r}.")
|
|
198
|
+
print(f"Expected tag: {expected}")
|
|
199
|
+
sys.exit(1)
|
|
200
|
+
|
|
201
|
+
print(f"Publishing homapy {version} from pyproject.toml.")
|
|
202
|
+
PY
|
|
203
|
+
|
|
204
|
+
- uses: actions/download-artifact@v4
|
|
205
|
+
with:
|
|
206
|
+
pattern: homapy-*
|
|
207
|
+
path: dist
|
|
208
|
+
merge-multiple: true
|
|
209
|
+
|
|
210
|
+
- name: Publish to TestPyPI
|
|
211
|
+
if: github.event_name == 'workflow_dispatch' && github.event.inputs.publish == 'testpypi'
|
|
212
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
213
|
+
with:
|
|
214
|
+
repository-url: https://test.pypi.org/legacy/
|
|
215
|
+
packages-dir: dist
|
|
216
|
+
|
|
217
|
+
- name: Publish to PyPI
|
|
218
|
+
if: startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && github.event.inputs.publish == 'pypi')
|
|
219
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
220
|
+
with:
|
|
221
|
+
packages-dir: dist
|
homapy-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
build/
|
|
2
|
+
build_debug/
|
|
3
|
+
cmake-build-release
|
|
4
|
+
cmake-build-debug
|
|
5
|
+
.vscode/
|
|
6
|
+
.idea/
|
|
7
|
+
.cursor/
|
|
8
|
+
scripts/*.log
|
|
9
|
+
scripts/*.ini
|
|
10
|
+
scripts/*.nsys-rep
|
|
11
|
+
scripts/*.sqlite
|
|
12
|
+
scripts/*.obj
|
|
13
|
+
|
|
14
|
+
# Logs anywhere in the tree
|
|
15
|
+
*.log
|
|
16
|
+
|
|
17
|
+
# CMake scratch dir kept outside of build/
|
|
18
|
+
.tmp_build/
|
|
19
|
+
|
|
20
|
+
# GUI / runtime state files (ImGui, Polyscope, etc.)
|
|
21
|
+
imgui.ini
|
|
22
|
+
.polyscope.ini
|
|
23
|
+
*.mtx
|
|
24
|
+
/scripts/examples/results
|
|
25
|
+
*.pyc
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.24 FATAL_ERROR)
|
|
2
|
+
|
|
3
|
+
project(Homa
|
|
4
|
+
VERSION 0.1.0
|
|
5
|
+
LANGUAGES C CXX)
|
|
6
|
+
|
|
7
|
+
set(HOMA_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
|
8
|
+
set(HOMA_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
|
9
|
+
|
|
10
|
+
if(PROJECT_IS_TOP_LEVEL AND NOT CMAKE_CONFIGURATION_TYPES AND "${CMAKE_BUILD_TYPE}" STREQUAL "")
|
|
11
|
+
set(CMAKE_BUILD_TYPE Release)
|
|
12
|
+
endif ()
|
|
13
|
+
|
|
14
|
+
################################################################################
|
|
15
|
+
# HOMA OPTIONS
|
|
16
|
+
################################################################################
|
|
17
|
+
option(HOMA_BUILD_EXAMPLE "Build example executables" OFF)
|
|
18
|
+
option(HOMA_BUILD_TESTS "Build unit tests" OFF)
|
|
19
|
+
option(HOMA_BUILD_PYTHON "Build Python bindings" OFF)
|
|
20
|
+
option(HOMA_WITH_CUDA "Enable CUDA / GPU backend" ON)
|
|
21
|
+
option(HOMA_WITH_CHOLMOD "Enable CHOLMOD linear solver" ON)
|
|
22
|
+
option(HOMA_WITH_MKL "Enable MKL linear solver" ON)
|
|
23
|
+
option(HOMA_WITH_CUDSS "Enable cuDSS linear solver" ON)
|
|
24
|
+
option(HOMA_WITH_LLOYD_PATCHER "Enable Lloyd-clustering patcher" ON)
|
|
25
|
+
option(HOMA_WITH_PROFILE "Use Profile for benchmark" OFF)
|
|
26
|
+
|
|
27
|
+
set(_homa_needs_cuda OFF)
|
|
28
|
+
if(HOMA_WITH_CUDA OR HOMA_WITH_CUDSS)
|
|
29
|
+
set(_homa_needs_cuda ON)
|
|
30
|
+
endif()
|
|
31
|
+
|
|
32
|
+
message(STATUS "HOMA_BUILD_EXAMPLE: ${HOMA_BUILD_EXAMPLE}")
|
|
33
|
+
message(STATUS "HOMA_BUILD_TESTS: ${HOMA_BUILD_TESTS}")
|
|
34
|
+
message(STATUS "HOMA_BUILD_PYTHON: ${HOMA_BUILD_PYTHON}")
|
|
35
|
+
message(STATUS "HOMA_WITH_CUDA: ${HOMA_WITH_CUDA}")
|
|
36
|
+
message(STATUS "HOMA_WITH_CHOLMOD: ${HOMA_WITH_CHOLMOD}")
|
|
37
|
+
message(STATUS "HOMA_WITH_MKL: ${HOMA_WITH_MKL}")
|
|
38
|
+
message(STATUS "HOMA_WITH_CUDSS: ${HOMA_WITH_CUDSS}")
|
|
39
|
+
message(STATUS "HOMA_WITH_LLOYD_PATCHER: ${HOMA_WITH_LLOYD_PATCHER}")
|
|
40
|
+
message(STATUS "HOMA_WITH_PROFILE: ${HOMA_WITH_PROFILE}")
|
|
41
|
+
message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
|
|
42
|
+
|
|
43
|
+
if(PROJECT_IS_TOP_LEVEL)
|
|
44
|
+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
|
45
|
+
endif()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
49
|
+
|
|
50
|
+
if(_homa_needs_cuda AND
|
|
51
|
+
NOT DEFINED CMAKE_CUDA_ARCHITECTURES AND
|
|
52
|
+
"$ENV{CUDAARCHS}" STREQUAL "")
|
|
53
|
+
set(CMAKE_CUDA_ARCHITECTURES native CACHE STRING "CUDA architectures")
|
|
54
|
+
endif()
|
|
55
|
+
|
|
56
|
+
if(_homa_needs_cuda)
|
|
57
|
+
enable_language(CUDA)
|
|
58
|
+
message(STATUS "CMAKE_CUDA_ARCHITECTURES: ${CMAKE_CUDA_ARCHITECTURES}")
|
|
59
|
+
endif()
|
|
60
|
+
|
|
61
|
+
set(CMAKE_CXX_STANDARD 20)
|
|
62
|
+
set(CMAKE_CUDA_STANDARD 20)
|
|
63
|
+
set(CMAKE_CUDA_STANDARD_REQUIRED TRUE)
|
|
64
|
+
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
|
65
|
+
|
|
66
|
+
if(_homa_needs_cuda)
|
|
67
|
+
set(CMAKE_CUDA_STANDARD 20)
|
|
68
|
+
set(CMAKE_CUDA_STANDARD_REQUIRED TRUE)
|
|
69
|
+
set(CUDA_RESOLVE_DEVICE_SYMBOLS ON)
|
|
70
|
+
set(CUDA_SEPARABLE_COMPILATION ON)
|
|
71
|
+
endif()
|
|
72
|
+
|
|
73
|
+
################################################################################
|
|
74
|
+
# SECTION 1: Include Required Dependencies
|
|
75
|
+
################################################################################
|
|
76
|
+
|
|
77
|
+
set(cxx_flags
|
|
78
|
+
$<$<CXX_COMPILER_ID:MSVC>:-D_SCL_SECURE_NO_WARNINGS /openmp:experimental /MP /std:c++20 /bigobj>
|
|
79
|
+
$<$<AND:$<CXX_COMPILER_ID:GNU>,$<CONFIG:Release>>:-Wall -m64 -fopenmp -O3 -Wno-unused-function>
|
|
80
|
+
$<$<AND:$<CXX_COMPILER_ID:GNU>,$<CONFIG:Debug>>:-Wall -m64 -fopenmp -O0 -g3 -Wno-unused-function>
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
set(MSVC_XCOMPILER_FLAGS "/openmp:experimental /MP /std:c++20 /Zi")
|
|
84
|
+
|
|
85
|
+
set(cuda_flags
|
|
86
|
+
#Windows stuff
|
|
87
|
+
-Xcompiler=$<$<CXX_COMPILER_ID:MSVC>:${MSVC_XCOMPILER_FLAGS}>
|
|
88
|
+
# Release
|
|
89
|
+
$<$<AND:$<CXX_COMPILER_ID:GNU>,$<CONFIG:Release>>:
|
|
90
|
+
-Xcompiler=-rdynamic,-Wall,-fopenmp,-O3,-Wno-unused-function
|
|
91
|
+
-O3
|
|
92
|
+
>
|
|
93
|
+
# Debug
|
|
94
|
+
$<$<AND:$<CXX_COMPILER_ID:GNU>,$<CONFIG:Debug>>:
|
|
95
|
+
-G
|
|
96
|
+
-O0
|
|
97
|
+
-Xptxas=-O0
|
|
98
|
+
-lineinfo
|
|
99
|
+
-Xcompiler=-rdynamic,-Wall,-fopenmp,-O0,-g3,-Wno-unused-function
|
|
100
|
+
>
|
|
101
|
+
# other common CUDA flags here
|
|
102
|
+
-rdc=true
|
|
103
|
+
--expt-extended-lambda
|
|
104
|
+
--expt-relaxed-constexpr
|
|
105
|
+
-Xptxas -warn-spills -res-usage
|
|
106
|
+
--ptxas-options=-v
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
add_library(homa_flags INTERFACE)
|
|
110
|
+
target_compile_options(homa_flags INTERFACE
|
|
111
|
+
$<$<COMPILE_LANGUAGE:CXX>:${cxx_flags}>
|
|
112
|
+
$<$<COMPILE_LANGUAGE:CUDA>:${cuda_flags}>
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# OpenMP
|
|
116
|
+
find_package(OpenMP)
|
|
117
|
+
if (OpenMP_CXX_FOUND)
|
|
118
|
+
target_link_libraries(homa_flags INTERFACE OpenMP::OpenMP_CXX)
|
|
119
|
+
endif()
|
|
120
|
+
|
|
121
|
+
if(_homa_needs_cuda)
|
|
122
|
+
find_package(CUDAToolkit REQUIRED)
|
|
123
|
+
target_link_libraries(homa_flags INTERFACE CUDA::cudart CUDA::cusparse CUDA::cusolver)
|
|
124
|
+
endif()
|
|
125
|
+
|
|
126
|
+
# Core deps — always needed for the homa library
|
|
127
|
+
include(${HOMA_SOURCE_DIR}/cmake/recipes/eigen.cmake)
|
|
128
|
+
include(${HOMA_SOURCE_DIR}/cmake/recipes/metis.cmake)
|
|
129
|
+
include(${HOMA_SOURCE_DIR}/cmake/recipes/spdlog.cmake)
|
|
130
|
+
# SuiteSparse/AMD is always needed: cpu_ordering_with_patch uses amd.h for local ordering
|
|
131
|
+
include(${HOMA_SOURCE_DIR}/cmake/recipes/suitesparse.cmake)
|
|
132
|
+
|
|
133
|
+
if(HOMA_WITH_LLOYD_PATCHER)
|
|
134
|
+
include(${HOMA_SOURCE_DIR}/cmake/recipes/lloyd_clustering.cmake)
|
|
135
|
+
endif()
|
|
136
|
+
|
|
137
|
+
if(HOMA_WITH_MKL)
|
|
138
|
+
set(HOMA_MKL_ALLOW_DOWNLOAD ON CACHE BOOL "Download Intel MKL wheels when an installed MKL is not found")
|
|
139
|
+
set(HOMA_MKL_VERSION "2025.3.0" CACHE STRING "Intel MKL wheel fallback version")
|
|
140
|
+
set(HOMA_MKL_INTERFACE "lp64" CACHE STRING "Intel MKL interface layer")
|
|
141
|
+
set(HOMA_MKL_THREADING "intel" CACHE STRING "Intel MKL threading layer")
|
|
142
|
+
set(HOMA_MKL_LINKING "sdl" CACHE STRING "Intel MKL linking mode")
|
|
143
|
+
set_property(CACHE HOMA_MKL_INTERFACE PROPERTY STRINGS lp64)
|
|
144
|
+
set_property(CACHE HOMA_MKL_THREADING PROPERTY STRINGS intel sequential)
|
|
145
|
+
set_property(CACHE HOMA_MKL_LINKING PROPERTY STRINGS sdl)
|
|
146
|
+
include(${HOMA_SOURCE_DIR}/cmake/recipes/mkl.cmake)
|
|
147
|
+
endif()
|
|
148
|
+
|
|
149
|
+
if(HOMA_WITH_CHOLMOD)
|
|
150
|
+
include(${HOMA_SOURCE_DIR}/cmake/recipes/cholmod.cmake)
|
|
151
|
+
endif()
|
|
152
|
+
|
|
153
|
+
if(HOMA_WITH_CUDSS)
|
|
154
|
+
set(HOMA_CUDSS_ALLOW_DOWNLOAD ON CACHE BOOL "Download NVIDIA cuDSS wheels when an installed cuDSS is not found")
|
|
155
|
+
set(HOMA_CUDSS_VERSION "0.7.1.6" CACHE STRING "NVIDIA cuDSS wheel fallback version")
|
|
156
|
+
include(${HOMA_SOURCE_DIR}/cmake/recipes/cudss.cmake)
|
|
157
|
+
endif()
|
|
158
|
+
|
|
159
|
+
if(HOMA_BUILD_EXAMPLE)
|
|
160
|
+
include(${HOMA_SOURCE_DIR}/cmake/recipes/cli11.cmake)
|
|
161
|
+
include(${HOMA_SOURCE_DIR}/cmake/recipes/libigl.cmake)
|
|
162
|
+
endif()
|
|
163
|
+
|
|
164
|
+
function(homa_configure_runtime target_name)
|
|
165
|
+
if(NOT TARGET ${target_name})
|
|
166
|
+
message(FATAL_ERROR "homa_configure_runtime: target '${target_name}' does not exist")
|
|
167
|
+
endif()
|
|
168
|
+
|
|
169
|
+
get_property(_homa_runtime_configured TARGET ${target_name} PROPERTY homa_runtime_configured)
|
|
170
|
+
if(_homa_runtime_configured)
|
|
171
|
+
return()
|
|
172
|
+
endif()
|
|
173
|
+
|
|
174
|
+
if(COMMAND homa_configure_mkl_runtime)
|
|
175
|
+
homa_configure_mkl_runtime(${target_name})
|
|
176
|
+
endif()
|
|
177
|
+
if(COMMAND homa_configure_cudss_runtime)
|
|
178
|
+
homa_configure_cudss_runtime(${target_name})
|
|
179
|
+
endif()
|
|
180
|
+
|
|
181
|
+
set_property(TARGET ${target_name} PROPERTY homa_runtime_configured TRUE)
|
|
182
|
+
endfunction()
|
|
183
|
+
|
|
184
|
+
# Create a dependency interface target to hold configuration
|
|
185
|
+
add_library(homa_deps INTERFACE)
|
|
186
|
+
|
|
187
|
+
################################################################################
|
|
188
|
+
# SECTION 3: Configure Dependencies
|
|
189
|
+
################################################################################
|
|
190
|
+
|
|
191
|
+
if(HOMA_WITH_PROFILE)
|
|
192
|
+
target_compile_definitions(homa_deps INTERFACE USE_PROFILE)
|
|
193
|
+
endif()
|
|
194
|
+
|
|
195
|
+
if(TARGET Eigen3::Eigen)
|
|
196
|
+
get_target_property(EIGEN_INCLUDES Eigen3::Eigen INTERFACE_INCLUDE_DIRECTORIES)
|
|
197
|
+
message(STATUS "=== EIGEN DEBUG ===")
|
|
198
|
+
message(STATUS "Eigen3::Eigen include dirs: ${EIGEN_INCLUDES}")
|
|
199
|
+
message(STATUS "===================")
|
|
200
|
+
endif()
|
|
201
|
+
|
|
202
|
+
set(_homa_sources
|
|
203
|
+
src/ordering/homa.cpp
|
|
204
|
+
src/ordering/cpu_ordering_with_patch.cpp
|
|
205
|
+
src/ordering/amd_order_helper.cpp
|
|
206
|
+
src/patching/greedy_patcher.cpp
|
|
207
|
+
src/patching/metis_patcher.cpp
|
|
208
|
+
src/utils/remove_diagonal.cpp
|
|
209
|
+
src/utils/check_valid_permutation.cpp
|
|
210
|
+
src/utils/compress_hessian.cpp
|
|
211
|
+
src/solvers/LinSysSolver.cpp
|
|
212
|
+
include/homa/solvers/LinSysSolver.h
|
|
213
|
+
include/homa/solvers/CHOLMODSolver.h
|
|
214
|
+
include/homa/solvers/CUDSSSolver.h
|
|
215
|
+
include/homa/solvers/MKLSolver.h
|
|
216
|
+
include/homa/solvers/scalar_traits.h
|
|
217
|
+
include/homa/matrix_view.h
|
|
218
|
+
include/homa/homa.h
|
|
219
|
+
include/homa/patcher.h
|
|
220
|
+
include/homa/types.h
|
|
221
|
+
include/homa/utils/check_valid_permutation.h
|
|
222
|
+
include/homa/utils/compress_hessian.h
|
|
223
|
+
include/homa/utils/nvtx_helper.h
|
|
224
|
+
include/homa/utils/remove_diagonal.h
|
|
225
|
+
include/homa/utils/SPD_cot_matrix.h
|
|
226
|
+
)
|
|
227
|
+
if(HOMA_WITH_LLOYD_PATCHER)
|
|
228
|
+
list(APPEND _homa_sources src/patching/lloyd_patcher.cpp)
|
|
229
|
+
endif()
|
|
230
|
+
if(HOMA_WITH_CHOLMOD)
|
|
231
|
+
list(APPEND _homa_sources
|
|
232
|
+
src/solvers/CHOLMODSolver.cpp
|
|
233
|
+
include/homa/solvers/CHOLMODSolver.h)
|
|
234
|
+
endif()
|
|
235
|
+
if(HOMA_WITH_MKL)
|
|
236
|
+
list(APPEND _homa_sources
|
|
237
|
+
src/solvers/MKLSolver.cpp
|
|
238
|
+
include/homa/solvers/MKLSolver.h)
|
|
239
|
+
endif()
|
|
240
|
+
if(HOMA_WITH_CUDSS)
|
|
241
|
+
list(APPEND _homa_sources
|
|
242
|
+
src/solvers/CUDSSSolver.cu
|
|
243
|
+
include/homa/solvers/CUDSSSolver.h
|
|
244
|
+
include/homa/utils/cuda_error_handler.h)
|
|
245
|
+
endif()
|
|
246
|
+
|
|
247
|
+
add_library(homa STATIC ${_homa_sources})
|
|
248
|
+
|
|
249
|
+
target_include_directories(homa
|
|
250
|
+
PUBLIC include
|
|
251
|
+
PRIVATE src
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
set(_homa_public_libs
|
|
255
|
+
homa_deps
|
|
256
|
+
Eigen3::Eigen
|
|
257
|
+
spdlog::spdlog
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
if(HOMA_WITH_MKL)
|
|
261
|
+
list(APPEND _homa_public_libs Homa::MKL)
|
|
262
|
+
endif()
|
|
263
|
+
|
|
264
|
+
list(APPEND _homa_public_libs metis)
|
|
265
|
+
|
|
266
|
+
target_link_libraries(homa
|
|
267
|
+
PUBLIC ${_homa_public_libs}
|
|
268
|
+
PRIVATE
|
|
269
|
+
homa_flags
|
|
270
|
+
SuiteSparse::AMD
|
|
271
|
+
)
|
|
272
|
+
target_include_directories(homa PRIVATE ${AMD_INCLUDE_DIR} ${SUITESPARSE_CONFIG_INCLUDE_DIR})
|
|
273
|
+
target_compile_definitions(homa PUBLIC
|
|
274
|
+
$<$<CONFIG:Debug>:DEBUG>
|
|
275
|
+
$<$<CONFIG:Release>:NDEBUG>
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
if(_homa_needs_cuda)
|
|
279
|
+
target_link_libraries(homa PUBLIC CUDA::cudart)
|
|
280
|
+
endif()
|
|
281
|
+
|
|
282
|
+
if(HOMA_WITH_LLOYD_PATCHER)
|
|
283
|
+
target_link_libraries(homa PRIVATE mesh_clustering_lib)
|
|
284
|
+
target_compile_definitions(homa PRIVATE HOMA_WITH_LLOYD_PATCHER)
|
|
285
|
+
endif()
|
|
286
|
+
|
|
287
|
+
if(HOMA_WITH_MKL)
|
|
288
|
+
target_compile_definitions(homa PUBLIC USE_MKL)
|
|
289
|
+
endif()
|
|
290
|
+
|
|
291
|
+
if(HOMA_WITH_CHOLMOD)
|
|
292
|
+
target_link_libraries(homa PUBLIC SuiteSparse::CHOLMOD)
|
|
293
|
+
target_compile_definitions(homa PUBLIC USE_CHOLMOD)
|
|
294
|
+
endif()
|
|
295
|
+
|
|
296
|
+
if(HOMA_WITH_CUDSS)
|
|
297
|
+
target_link_libraries(homa PUBLIC cudss)
|
|
298
|
+
target_compile_definitions(homa PUBLIC USE_CUDSS)
|
|
299
|
+
set_property(TARGET homa PROPERTY CUDA_SEPARABLE_COMPILATION ON)
|
|
300
|
+
set_property(TARGET homa PROPERTY CUDA_RESOLVE_DEVICE_SYMBOLS ON)
|
|
301
|
+
endif()
|
|
302
|
+
|
|
303
|
+
add_library(Homa::homa ALIAS homa)
|
|
304
|
+
|
|
305
|
+
if(HOMA_BUILD_TESTS)
|
|
306
|
+
enable_testing()
|
|
307
|
+
add_subdirectory(tests)
|
|
308
|
+
endif()
|
|
309
|
+
|
|
310
|
+
if(HOMA_BUILD_EXAMPLE)
|
|
311
|
+
add_library(libigl_utils INTERFACE)
|
|
312
|
+
target_link_libraries(libigl_utils INTERFACE igl::core Eigen3::Eigen)
|
|
313
|
+
target_include_directories(libigl_utils INTERFACE src/utils)
|
|
314
|
+
add_subdirectory(examples)
|
|
315
|
+
|
|
316
|
+
endif()
|
|
317
|
+
|
|
318
|
+
if(HOMA_BUILD_PYTHON)
|
|
319
|
+
add_subdirectory(python)
|
|
320
|
+
endif()
|
homapy-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
BSD 2-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, Behrooz Zarebavani and Ahmed Mahmoud
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
17
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
18
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
19
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
20
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
21
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
22
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
23
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
24
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
25
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|