lwbgt 0.3.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.
- lwbgt-0.3.0/.github/workflows/ci.yml +46 -0
- lwbgt-0.3.0/.github/workflows/release.yml +177 -0
- lwbgt-0.3.0/.github/workflows/wheels.yml +140 -0
- lwbgt-0.3.0/.gitignore +9 -0
- lwbgt-0.3.0/ABI.md +136 -0
- lwbgt-0.3.0/CHANGELOG.md +63 -0
- lwbgt-0.3.0/CITATION.cff +42 -0
- lwbgt-0.3.0/CMakeLists.txt +327 -0
- lwbgt-0.3.0/LICENSE +201 -0
- lwbgt-0.3.0/LICENSES/LicenseRef-UChicago-Argonne-WBGT-1.1.txt +41 -0
- lwbgt-0.3.0/LICENSING.md +22 -0
- lwbgt-0.3.0/NOTICE +15 -0
- lwbgt-0.3.0/PKG-INFO +237 -0
- lwbgt-0.3.0/README.md +208 -0
- lwbgt-0.3.0/RELEASING.md +56 -0
- lwbgt-0.3.0/UPSTREAM.md +19 -0
- lwbgt-0.3.0/benchmarks/README.md +45 -0
- lwbgt-0.3.0/benchmarks/baseline-gcc-13.3.0.json +62 -0
- lwbgt-0.3.0/benchmarks/benchmark.c +183 -0
- lwbgt-0.3.0/benchmarks/optimization-1-gcc-13.3.0.json +62 -0
- lwbgt-0.3.0/benchmarks/optimization-2-gcc-13.3.0.json +62 -0
- lwbgt-0.3.0/benchmarks/optimization-3-environment.json +41 -0
- lwbgt-0.3.0/benchmarks/optimization-3-gcc-13.3.0.json +62 -0
- lwbgt-0.3.0/benchmarks/optimization-3-gcc-16.2.0.json +62 -0
- lwbgt-0.3.0/benchmarks/optimization-3-profile.md +62 -0
- lwbgt-0.3.0/benchmarks/v0.2.0-environment.json +38 -0
- lwbgt-0.3.0/benchmarks/v0.2.0-gcc-13.3.0.json +62 -0
- lwbgt-0.3.0/cmake/lwbgt.def +5 -0
- lwbgt-0.3.0/cmake/lwbgt.exports +3 -0
- lwbgt-0.3.0/cmake/lwbgt.map +8 -0
- lwbgt-0.3.0/cmake/lwbgt.pc.in +11 -0
- lwbgt-0.3.0/cmake/lwbgtConfig.cmake.in +3 -0
- lwbgt-0.3.0/examples/README.md +22 -0
- lwbgt-0.3.0/examples/julia/example.jl +63 -0
- lwbgt-0.3.0/examples/python/example.py +84 -0
- lwbgt-0.3.0/examples/r/example.R +26 -0
- lwbgt-0.3.0/examples/r/lwbgt_r.c +107 -0
- lwbgt-0.3.0/include/lwbgt.h +88 -0
- lwbgt-0.3.0/pyproject.toml +69 -0
- lwbgt-0.3.0/python/lwbgt/__init__.py +7 -0
- lwbgt-0.3.0/python/lwbgt/_ffi.py +174 -0
- lwbgt-0.3.0/python/lwbgt/_types.py +40 -0
- lwbgt-0.3.0/python/lwbgt/py.typed +1 -0
- lwbgt-0.3.0/src/lwbgt_ffi.c +75 -0
- lwbgt-0.3.0/src/wbgt.c +1170 -0
- lwbgt-0.3.0/tests/API.md +63 -0
- lwbgt-0.3.0/tests/BASELINE.md +12 -0
- lwbgt-0.3.0/tests/HEATSTRESSBENCH.md +35 -0
- lwbgt-0.3.0/tests/RELEASE-0.1.0.md +36 -0
- lwbgt-0.3.0/tests/RELEASE-0.2.0.md +51 -0
- lwbgt-0.3.0/tests/RELEASE-0.2.1.md +32 -0
- lwbgt-0.3.0/tests/RELEASE.md +44 -0
- lwbgt-0.3.0/tests/batch.c +201 -0
- lwbgt-0.3.0/tests/check_distribution.py +86 -0
- lwbgt-0.3.0/tests/check_exports.py +51 -0
- lwbgt-0.3.0/tests/check_versions.py +54 -0
- lwbgt-0.3.0/tests/compare.py +111 -0
- lwbgt-0.3.0/tests/consumer/CMakeLists.txt +11 -0
- lwbgt-0.3.0/tests/consumer/main.c +14 -0
- lwbgt-0.3.0/tests/consumer/main.cpp +28 -0
- lwbgt-0.3.0/tests/generate_cases.py +86 -0
- lwbgt-0.3.0/tests/probe.c +100 -0
- lwbgt-0.3.0/tests/python/_fixtures.py +63 -0
- lwbgt-0.3.0/tests/python/test_api.py +72 -0
- lwbgt-0.3.0/tests/python/test_batch.py +115 -0
- lwbgt-0.3.0/tests/python/test_distribution_check.py +36 -0
- lwbgt-0.3.0/tests/python/test_layout.py +61 -0
- lwbgt-0.3.0/tests/python/test_packaged_library.py +33 -0
- lwbgt-0.3.0/tests/test_install.cmake +35 -0
- lwbgt-0.3.0/upstream/wbgt.c.original +1144 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
contents: read
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
matrix:
|
|
14
|
+
include:
|
|
15
|
+
- os: ubuntu-latest
|
|
16
|
+
cc: gcc
|
|
17
|
+
- os: macos-15-intel
|
|
18
|
+
cc: clang
|
|
19
|
+
- os: windows-latest
|
|
20
|
+
cc: gcc
|
|
21
|
+
runs-on: ${{ matrix.os }}
|
|
22
|
+
env:
|
|
23
|
+
CC: ${{ matrix.cc }}
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v6
|
|
26
|
+
- uses: actions/setup-python@v6
|
|
27
|
+
with:
|
|
28
|
+
python-version: '3.10'
|
|
29
|
+
- name: Check version coherence
|
|
30
|
+
run: python tests/check_versions.py
|
|
31
|
+
- uses: r-lib/actions/setup-r@v2
|
|
32
|
+
with:
|
|
33
|
+
r-version: '4.3'
|
|
34
|
+
windows-path-include-mingw: true
|
|
35
|
+
- uses: julia-actions/setup-julia@v3
|
|
36
|
+
with:
|
|
37
|
+
version: '1.10'
|
|
38
|
+
- name: Configure
|
|
39
|
+
run: >-
|
|
40
|
+
cmake -S . -B build -G Ninja
|
|
41
|
+
-DCMAKE_BUILD_TYPE=Release
|
|
42
|
+
-DLWBGT_REQUIRE_ALL_BINDING_TESTS=ON
|
|
43
|
+
- name: Build
|
|
44
|
+
run: cmake --build build --parallel
|
|
45
|
+
- name: Test
|
|
46
|
+
run: ctest --test-dir build --output-on-failure
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
release-tag:
|
|
13
|
+
name: Verify annotated release tag
|
|
14
|
+
runs-on: ubuntu-24.04
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v6
|
|
17
|
+
with:
|
|
18
|
+
fetch-depth: 0
|
|
19
|
+
- name: Require an annotated tag object
|
|
20
|
+
run: test "$(git cat-file -t "$GITHUB_REF_NAME")" = tag
|
|
21
|
+
|
|
22
|
+
artifacts:
|
|
23
|
+
needs: release-tag
|
|
24
|
+
uses: ./.github/workflows/wheels.yml
|
|
25
|
+
|
|
26
|
+
testpypi-publish:
|
|
27
|
+
name: Publish verified artifacts to TestPyPI
|
|
28
|
+
needs: artifacts
|
|
29
|
+
runs-on: ubuntu-24.04
|
|
30
|
+
environment:
|
|
31
|
+
name: testpypi
|
|
32
|
+
url: https://test.pypi.org/project/lwbgt/
|
|
33
|
+
permissions:
|
|
34
|
+
contents: read
|
|
35
|
+
id-token: write
|
|
36
|
+
steps:
|
|
37
|
+
- uses: actions/download-artifact@v8
|
|
38
|
+
with:
|
|
39
|
+
pattern: dist-*
|
|
40
|
+
path: dist
|
|
41
|
+
merge-multiple: true
|
|
42
|
+
- name: Require the complete release matrix
|
|
43
|
+
run: |
|
|
44
|
+
test "$(find dist -maxdepth 1 -type f -name '*.whl' | wc -l)" -eq 5
|
|
45
|
+
test "$(find dist -maxdepth 1 -type f -name '*.tar.gz' | wc -l)" -eq 1
|
|
46
|
+
- name: Publish through TestPyPI Trusted Publishing
|
|
47
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
48
|
+
with:
|
|
49
|
+
repository-url: https://test.pypi.org/legacy/
|
|
50
|
+
|
|
51
|
+
testpypi-smoke:
|
|
52
|
+
name: Verify TestPyPI artifact identity and installation
|
|
53
|
+
needs: testpypi-publish
|
|
54
|
+
runs-on: ubuntu-24.04
|
|
55
|
+
steps:
|
|
56
|
+
- uses: actions/checkout@v6
|
|
57
|
+
- uses: actions/setup-python@v6
|
|
58
|
+
with:
|
|
59
|
+
python-version: '3.10'
|
|
60
|
+
- uses: actions/download-artifact@v8
|
|
61
|
+
with:
|
|
62
|
+
pattern: dist-*
|
|
63
|
+
path: dist
|
|
64
|
+
merge-multiple: true
|
|
65
|
+
- name: Download the release wheel from TestPyPI
|
|
66
|
+
run: |
|
|
67
|
+
version="${GITHUB_REF_NAME#v}"
|
|
68
|
+
mkdir testpypi
|
|
69
|
+
for attempt in $(seq 1 12); do
|
|
70
|
+
if python -m pip download \
|
|
71
|
+
--index-url https://test.pypi.org/simple/ \
|
|
72
|
+
--only-binary=:all: --no-cache-dir --no-deps \
|
|
73
|
+
--dest testpypi "lwbgt==$version"; then
|
|
74
|
+
break
|
|
75
|
+
fi
|
|
76
|
+
if test "$attempt" -eq 12; then
|
|
77
|
+
exit 1
|
|
78
|
+
fi
|
|
79
|
+
sleep 10
|
|
80
|
+
done
|
|
81
|
+
- name: Match the complete tested artifact set byte-for-byte
|
|
82
|
+
run: |
|
|
83
|
+
python - <<'PY'
|
|
84
|
+
import hashlib
|
|
85
|
+
import json
|
|
86
|
+
import os
|
|
87
|
+
import time
|
|
88
|
+
from pathlib import Path
|
|
89
|
+
from urllib.request import urlopen
|
|
90
|
+
|
|
91
|
+
version = os.environ["GITHUB_REF_NAME"].removeprefix("v")
|
|
92
|
+
expected = {
|
|
93
|
+
path.name: hashlib.sha256(path.read_bytes()).hexdigest()
|
|
94
|
+
for path in Path("dist").iterdir()
|
|
95
|
+
if path.is_file()
|
|
96
|
+
}
|
|
97
|
+
release_url = f"https://test.pypi.org/pypi/lwbgt/{version}/json"
|
|
98
|
+
published = {}
|
|
99
|
+
for attempt in range(12):
|
|
100
|
+
try:
|
|
101
|
+
with urlopen(release_url) as response:
|
|
102
|
+
release = json.load(response)
|
|
103
|
+
published = {
|
|
104
|
+
item["filename"]: item["digests"]["sha256"]
|
|
105
|
+
for item in release["urls"]
|
|
106
|
+
}
|
|
107
|
+
except OSError:
|
|
108
|
+
published = {}
|
|
109
|
+
if published == expected:
|
|
110
|
+
break
|
|
111
|
+
if attempt != 11:
|
|
112
|
+
time.sleep(10)
|
|
113
|
+
else:
|
|
114
|
+
raise SystemExit(
|
|
115
|
+
f"TestPyPI release differs: published={published}, expected={expected}"
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
downloaded = list(Path("testpypi").glob("*.whl"))
|
|
119
|
+
if len(downloaded) != 1:
|
|
120
|
+
raise SystemExit(f"expected one TestPyPI wheel, got {downloaded}")
|
|
121
|
+
expected_wheel = Path("dist", downloaded[0].name)
|
|
122
|
+
if not expected_wheel.is_file():
|
|
123
|
+
raise SystemExit(f"TestPyPI returned an unexpected artifact: {downloaded[0].name}")
|
|
124
|
+
actual_hash = hashlib.sha256(downloaded[0].read_bytes()).hexdigest()
|
|
125
|
+
expected_hash = hashlib.sha256(expected_wheel.read_bytes()).hexdigest()
|
|
126
|
+
if actual_hash != expected_hash:
|
|
127
|
+
raise SystemExit(
|
|
128
|
+
f"TestPyPI artifact hash mismatch: {actual_hash} != {expected_hash}"
|
|
129
|
+
)
|
|
130
|
+
print(f"TestPyPI release identity: {len(expected)} artifacts: ok")
|
|
131
|
+
print(f"TestPyPI wheel download: {downloaded[0].name}: {actual_hash}")
|
|
132
|
+
PY
|
|
133
|
+
- name: Test the wheel retrieved from TestPyPI
|
|
134
|
+
run: |
|
|
135
|
+
python -m venv testpypi-test
|
|
136
|
+
testpypi-test/bin/python -m pip install --no-index testpypi/*.whl
|
|
137
|
+
testpypi-test/bin/python -m unittest discover -s tests/python -v
|
|
138
|
+
|
|
139
|
+
publish:
|
|
140
|
+
name: Publish verified artifacts to PyPI
|
|
141
|
+
needs: [artifacts, testpypi-smoke]
|
|
142
|
+
runs-on: ubuntu-24.04
|
|
143
|
+
environment:
|
|
144
|
+
name: pypi
|
|
145
|
+
url: https://pypi.org/p/lwbgt
|
|
146
|
+
permissions:
|
|
147
|
+
contents: read
|
|
148
|
+
id-token: write
|
|
149
|
+
steps:
|
|
150
|
+
- uses: actions/download-artifact@v8
|
|
151
|
+
with:
|
|
152
|
+
pattern: dist-*
|
|
153
|
+
path: dist
|
|
154
|
+
merge-multiple: true
|
|
155
|
+
- name: Require the complete release matrix
|
|
156
|
+
run: |
|
|
157
|
+
test "$(find dist -maxdepth 1 -type f -name '*.whl' | wc -l)" -eq 5
|
|
158
|
+
test "$(find dist -maxdepth 1 -type f -name '*.tar.gz' | wc -l)" -eq 1
|
|
159
|
+
- name: Publish through PyPI Trusted Publishing
|
|
160
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
161
|
+
|
|
162
|
+
github-release:
|
|
163
|
+
name: Create GitHub release
|
|
164
|
+
needs: publish
|
|
165
|
+
runs-on: ubuntu-24.04
|
|
166
|
+
permissions:
|
|
167
|
+
contents: write
|
|
168
|
+
steps:
|
|
169
|
+
- uses: actions/download-artifact@v8
|
|
170
|
+
with:
|
|
171
|
+
pattern: dist-*
|
|
172
|
+
path: dist
|
|
173
|
+
merge-multiple: true
|
|
174
|
+
- name: Create release for the existing annotated tag
|
|
175
|
+
env:
|
|
176
|
+
GH_TOKEN: ${{ github.token }}
|
|
177
|
+
run: gh release create "$GITHUB_REF_NAME" dist/* --verify-tag --generate-notes
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
name: wheels
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
workflow_call:
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build-wheels:
|
|
12
|
+
name: ${{ matrix.artifact }} wheel
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
include:
|
|
17
|
+
- runner: ubuntu-24.04
|
|
18
|
+
artifact: linux-x86_64
|
|
19
|
+
arch: x86_64
|
|
20
|
+
platform: linux
|
|
21
|
+
- runner: ubuntu-24.04-arm
|
|
22
|
+
artifact: linux-aarch64
|
|
23
|
+
arch: aarch64
|
|
24
|
+
platform: linux
|
|
25
|
+
- runner: macos-15-intel
|
|
26
|
+
artifact: macos-x86_64
|
|
27
|
+
arch: x86_64
|
|
28
|
+
platform: macos
|
|
29
|
+
- runner: macos-15
|
|
30
|
+
artifact: macos-arm64
|
|
31
|
+
arch: arm64
|
|
32
|
+
platform: macos
|
|
33
|
+
- runner: windows-2025
|
|
34
|
+
artifact: windows-amd64
|
|
35
|
+
arch: AMD64
|
|
36
|
+
platform: windows
|
|
37
|
+
runs-on: ${{ matrix.runner }}
|
|
38
|
+
env:
|
|
39
|
+
CIBW_BUILD: cp310-*
|
|
40
|
+
CIBW_SKIP: '*-musllinux_*'
|
|
41
|
+
CIBW_ARCHS: ${{ matrix.arch }}
|
|
42
|
+
CIBW_TEST_COMMAND: python -m unittest discover -s {project}/tests/python -v
|
|
43
|
+
CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: >-
|
|
44
|
+
delvewheel repair --analyze-existing --exclude ucrtbase.dll
|
|
45
|
+
-w {dest_dir} -v {wheel}
|
|
46
|
+
steps:
|
|
47
|
+
- uses: actions/checkout@v6
|
|
48
|
+
- uses: actions/setup-python@v6
|
|
49
|
+
with:
|
|
50
|
+
python-version: '3.14'
|
|
51
|
+
- name: Provision standalone MinGW GCC
|
|
52
|
+
if: matrix.platform == 'windows'
|
|
53
|
+
id: mingw
|
|
54
|
+
uses: egor-tensin/setup-mingw@v3
|
|
55
|
+
with:
|
|
56
|
+
platform: x64
|
|
57
|
+
version: 12.2.0
|
|
58
|
+
- name: Select MinGW compiler
|
|
59
|
+
if: matrix.platform == 'windows'
|
|
60
|
+
shell: pwsh
|
|
61
|
+
run: |
|
|
62
|
+
"CC=${{ steps.mingw.outputs.gcc }}" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
|
63
|
+
"CMAKE_GENERATOR=Ninja" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
|
64
|
+
- name: Check version coherence
|
|
65
|
+
run: python tests/check_versions.py
|
|
66
|
+
- name: Build, repair, and test wheel
|
|
67
|
+
uses: pypa/cibuildwheel@v4.1.1
|
|
68
|
+
- name: Inspect wheel contents
|
|
69
|
+
run: python tests/check_distribution.py "wheelhouse/*.whl"
|
|
70
|
+
- name: Inspect Linux dependencies
|
|
71
|
+
if: matrix.platform == 'linux'
|
|
72
|
+
run: |
|
|
73
|
+
python -m pip install auditwheel
|
|
74
|
+
for wheel in wheelhouse/*.whl; do
|
|
75
|
+
auditwheel show "$wheel"
|
|
76
|
+
done
|
|
77
|
+
- name: Inspect macOS dependencies
|
|
78
|
+
if: matrix.platform == 'macos'
|
|
79
|
+
run: python -m pip install delocate && delocate-listdeps wheelhouse/*.whl
|
|
80
|
+
- name: Inspect Windows dependencies
|
|
81
|
+
if: matrix.platform == 'windows'
|
|
82
|
+
run: python -m pip install delvewheel && delvewheel show --analyze-existing wheelhouse\*.whl
|
|
83
|
+
- uses: actions/upload-artifact@v7
|
|
84
|
+
with:
|
|
85
|
+
name: dist-${{ matrix.artifact }}
|
|
86
|
+
path: wheelhouse/*.whl
|
|
87
|
+
if-no-files-found: error
|
|
88
|
+
|
|
89
|
+
build-sdist:
|
|
90
|
+
name: source distribution
|
|
91
|
+
runs-on: ubuntu-24.04
|
|
92
|
+
steps:
|
|
93
|
+
- uses: actions/checkout@v6
|
|
94
|
+
- uses: actions/setup-python@v6
|
|
95
|
+
with:
|
|
96
|
+
python-version: '3.14'
|
|
97
|
+
- name: Check version coherence
|
|
98
|
+
run: python tests/check_versions.py
|
|
99
|
+
- name: Build source distribution
|
|
100
|
+
run: |
|
|
101
|
+
python -m pip install build twine
|
|
102
|
+
python -m build --sdist
|
|
103
|
+
python tests/check_distribution.py "dist/*.tar.gz"
|
|
104
|
+
python -m twine check dist/*
|
|
105
|
+
- name: Rebuild wheel from source distribution
|
|
106
|
+
run: |
|
|
107
|
+
python -m pip wheel --no-deps --wheel-dir sdist-wheel dist/*.tar.gz
|
|
108
|
+
python tests/check_distribution.py "sdist-wheel/*.whl"
|
|
109
|
+
- name: Test source-built wheel in a clean environment
|
|
110
|
+
run: |
|
|
111
|
+
python -m venv sdist-test
|
|
112
|
+
sdist-test/bin/python -m pip install --no-index sdist-wheel/*.whl
|
|
113
|
+
sdist-test/bin/python -m unittest discover -s tests/python -v
|
|
114
|
+
- uses: actions/upload-artifact@v7
|
|
115
|
+
with:
|
|
116
|
+
name: dist-sdist
|
|
117
|
+
path: dist/*.tar.gz
|
|
118
|
+
if-no-files-found: error
|
|
119
|
+
|
|
120
|
+
python-compatibility:
|
|
121
|
+
name: Linux wheel on Python ${{ matrix.python }}
|
|
122
|
+
needs: build-wheels
|
|
123
|
+
runs-on: ubuntu-24.04
|
|
124
|
+
strategy:
|
|
125
|
+
fail-fast: false
|
|
126
|
+
matrix:
|
|
127
|
+
python: ['3.10', '3.x']
|
|
128
|
+
steps:
|
|
129
|
+
- uses: actions/checkout@v6
|
|
130
|
+
- uses: actions/setup-python@v6
|
|
131
|
+
with:
|
|
132
|
+
python-version: ${{ matrix.python }}
|
|
133
|
+
- uses: actions/download-artifact@v8
|
|
134
|
+
with:
|
|
135
|
+
name: dist-linux-x86_64
|
|
136
|
+
path: dist
|
|
137
|
+
- name: Install the same ABI-independent wheel
|
|
138
|
+
run: |
|
|
139
|
+
python -m pip install --no-index dist/*.whl
|
|
140
|
+
python -m unittest discover -s tests/python -v
|
lwbgt-0.3.0/.gitignore
ADDED
lwbgt-0.3.0/ABI.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# ABI contract
|
|
2
|
+
|
|
3
|
+
This document defines the supported binary interface for lwbgt. Public symbols
|
|
4
|
+
and layouts described here are compatibility commitments; other link-visible
|
|
5
|
+
symbols in the static archive are implementation details.
|
|
6
|
+
|
|
7
|
+
## Versioning
|
|
8
|
+
|
|
9
|
+
The project release version and FFI ABI version are independent:
|
|
10
|
+
|
|
11
|
+
- `LWBGT_VERSION_MAJOR`, `LWBGT_VERSION_MINOR`, and `LWBGT_VERSION_PATCH`
|
|
12
|
+
identify the project release.
|
|
13
|
+
- `LWBGT_FFI_ABI_VERSION` identifies the versioned structure and batch API.
|
|
14
|
+
- The `calc_wbgt` and `esat` scalar symbols retain the original compatibility
|
|
15
|
+
ABI.
|
|
16
|
+
- The `lwbgt_input_v1`, `lwbgt_output_v1`, and `lwbgt_calc_batch_v1` names are
|
|
17
|
+
permanent. Incompatible layouts or behavior require new `v2` names while the
|
|
18
|
+
v1 entry point remains available.
|
|
19
|
+
|
|
20
|
+
New symbols and backward-compatible documentation clarifications may be added
|
|
21
|
+
without changing the v1 ABI. Fields must not be reordered, resized, removed, or
|
|
22
|
+
repurposed.
|
|
23
|
+
|
|
24
|
+
## Data model and layout
|
|
25
|
+
|
|
26
|
+
The v1 ABI requires 8-bit bytes, 32-bit `int32_t` and `float`, 64-bit `double`,
|
|
27
|
+
and the field offsets below. Supported release builds enforce the total sizes
|
|
28
|
+
and boundary offsets with compile-time assertions.
|
|
29
|
+
|
|
30
|
+
### `lwbgt_input_v1`
|
|
31
|
+
|
|
32
|
+
Total size: 104 bytes. Integer fields occupy the first 32 bytes; every floating
|
|
33
|
+
point input is an ABI-boundary `double`.
|
|
34
|
+
|
|
35
|
+
| Offset | Field | Type | Units and meaning |
|
|
36
|
+
|---:|---|---|---|
|
|
37
|
+
| 0 | `year` | `int32_t` | Four-digit Gregorian year |
|
|
38
|
+
| 4 | `month` | `int32_t` | Month 1–12; 0 means `day` is day-of-year |
|
|
39
|
+
| 8 | `day` | `int32_t` | Day of month, or day-of-year when `month == 0` |
|
|
40
|
+
| 12 | `hour` | `int32_t` | Local standard-time hour, 0–23 |
|
|
41
|
+
| 16 | `minute` | `int32_t` | Minutes past the hour |
|
|
42
|
+
| 20 | `gmt_offset_hours` | `int32_t` | Local standard time minus GMT, in hours |
|
|
43
|
+
| 24 | `averaging_minutes` | `int32_t` | Input averaging interval in minutes |
|
|
44
|
+
| 28 | `urban` | `int32_t` | 0 selects rural; 1 selects urban wind scaling |
|
|
45
|
+
| 32 | `latitude_deg_north` | `double` | Degrees north; south is negative |
|
|
46
|
+
| 40 | `longitude_deg_east` | `double` | Degrees east; west is negative |
|
|
47
|
+
| 48 | `solar_w_m2` | `double` | Solar irradiance, W/m² |
|
|
48
|
+
| 56 | `pressure_hpa` | `double` | Barometric pressure, hPa (equivalent to mb) |
|
|
49
|
+
| 64 | `air_temperature_c` | `double` | Dry-bulb air temperature, °C |
|
|
50
|
+
| 72 | `relative_humidity_percent` | `double` | Relative humidity, percent |
|
|
51
|
+
| 80 | `wind_speed_m_s` | `double` | Wind speed, m/s |
|
|
52
|
+
| 88 | `wind_height_m` | `double` | Wind measurement height, m |
|
|
53
|
+
| 96 | `vertical_temperature_difference_c` | `double` | Upper-minus-lower temperature difference, °C |
|
|
54
|
+
|
|
55
|
+
### `lwbgt_output_v1`
|
|
56
|
+
|
|
57
|
+
Total size: 24 bytes.
|
|
58
|
+
|
|
59
|
+
| Offset | Field | Type | Meaning |
|
|
60
|
+
|---:|---|---|---|
|
|
61
|
+
| 0 | `status` | `int32_t` | Per-record scalar solver status |
|
|
62
|
+
| 4 | `estimated_wind_speed_m_s` | `float` | Effective wind speed at 2 m, m/s |
|
|
63
|
+
| 8 | `globe_temperature_c` | `float` | Globe temperature, °C |
|
|
64
|
+
| 12 | `natural_wet_bulb_c` | `float` | Natural wet-bulb temperature, °C |
|
|
65
|
+
| 16 | `psychrometric_wet_bulb_c` | `float` | Psychrometric wet-bulb temperature, °C |
|
|
66
|
+
| 20 | `wbgt_c` | `float` | Outdoor wet-bulb globe temperature, °C |
|
|
67
|
+
|
|
68
|
+
## Batch call contract
|
|
69
|
+
|
|
70
|
+
```c
|
|
71
|
+
int lwbgt_calc_batch_v1(
|
|
72
|
+
const lwbgt_input_v1 *inputs,
|
|
73
|
+
lwbgt_output_v1 *outputs,
|
|
74
|
+
size_t count
|
|
75
|
+
);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
- `count == 0` returns `LWBGT_BATCH_OK`; either pointer may be null.
|
|
79
|
+
- For nonzero `count`, a null pointer returns
|
|
80
|
+
`LWBGT_BATCH_INVALID_ARGUMENT` without modifying outputs.
|
|
81
|
+
- The caller owns both arrays and must provide at least `count` elements. The
|
|
82
|
+
input and output storage must not overlap.
|
|
83
|
+
- Records execute serially, in ascending array order, by calling the scalar
|
|
84
|
+
implementation once per record.
|
|
85
|
+
- The function return value reports call validity. Each output `status` reports
|
|
86
|
+
that record's scalar solver result: 0 for success and -1 for failure to
|
|
87
|
+
converge. A failed record uses the upstream `-9999` result convention.
|
|
88
|
+
- Inputs are forwarded without domain validation, clamping, unit conversion, or
|
|
89
|
+
missing-value policy beyond behavior already present in the scalar model.
|
|
90
|
+
- When wind is already measured at 2 m, the batch API returns the supplied wind
|
|
91
|
+
as `estimated_wind_speed_m_s`. This makes the batch result deterministic; the
|
|
92
|
+
legacy scalar function instead leaves that output pointer untouched when no
|
|
93
|
+
estimation is performed.
|
|
94
|
+
|
|
95
|
+
## Scalar ABI
|
|
96
|
+
|
|
97
|
+
The declarations in `lwbgt.h` are authoritative. Scalar floating-point inputs
|
|
98
|
+
to `calc_wbgt` use `double` at the ABI boundary because the original K&R
|
|
99
|
+
`float` parameters undergo default argument promotion. Output pointers remain
|
|
100
|
+
`float *`.
|
|
101
|
+
|
|
102
|
+
`esat` accepts temperature in kelvin. `phase == 0` computes saturation over
|
|
103
|
+
liquid water; `phase == 1` computes saturation over ice. Other phase values are
|
|
104
|
+
outside the supported contract.
|
|
105
|
+
|
|
106
|
+
## Concurrency and ownership
|
|
107
|
+
|
|
108
|
+
The implementation has no mutable shared calculation state. Independent scalar
|
|
109
|
+
or batch calls are thread-safe when callers use separate output buffers. A
|
|
110
|
+
single batch call is serial and does not create threads. The API retains no
|
|
111
|
+
input or output pointers after return and performs no allocation.
|
|
112
|
+
|
|
113
|
+
## Symbols and platforms
|
|
114
|
+
|
|
115
|
+
The shared library exports only:
|
|
116
|
+
|
|
117
|
+
```text
|
|
118
|
+
calc_wbgt
|
|
119
|
+
esat
|
|
120
|
+
lwbgt_calc_batch_v1
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The release CI validates Linux with GCC, macOS with AppleClang, and Windows with
|
|
124
|
+
MinGW GCC. MSVC is unsupported because it cannot compile the preserved GNU89
|
|
125
|
+
numerical source. The public header is valid C and C++ and is tested through
|
|
126
|
+
installed C and C++ consumers.
|
|
127
|
+
|
|
128
|
+
## Official Python binding
|
|
129
|
+
|
|
130
|
+
The `lwbgt` Python distribution loads its bundled unversioned runtime through
|
|
131
|
+
`importlib.resources` and `ctypes`. Its public `Input` and `Result` records map
|
|
132
|
+
field-for-field to the v1 structures above. `calculate` and `calculate_batch`
|
|
133
|
+
both use `lwbgt_calc_batch_v1`; the latter submits the entire iterable in one
|
|
134
|
+
native call. `esat` directly exposes the scalar symbol. The binding performs no
|
|
135
|
+
unit conversion, domain validation, clamping, missing-data handling, or solver
|
|
136
|
+
failure substitution.
|
lwbgt-0.3.0/CHANGELOG.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## v0.3.0 — 2026-08-19
|
|
4
|
+
|
|
5
|
+
- Added the official dependency-free Python API: immutable `Input` and `Result`
|
|
6
|
+
records plus `calculate`, `calculate_batch`, and `esat`.
|
|
7
|
+
- Added an unversioned, wheel-only shared target built from the existing native
|
|
8
|
+
objects with the same restricted three-symbol export surface.
|
|
9
|
+
- Added platform-specific, Python-ABI-independent wheel and rebuildable sdist
|
|
10
|
+
packaging through scikit-build-core.
|
|
11
|
+
- Added installed-wheel ABI layout, resource loading, scalar, batch, failure,
|
|
12
|
+
`esat`, deterministic fixture, archive licensing, and version-coherence tests.
|
|
13
|
+
- Added cibuildwheel coverage for manylinux x86_64/aarch64, macOS x86_64/arm64,
|
|
14
|
+
and Windows amd64, plus OIDC Trusted Publishing release automation.
|
|
15
|
+
|
|
16
|
+
## v0.2.1 — 2026-08-18
|
|
17
|
+
|
|
18
|
+
- Licensed project-authored files under Apache-2.0 while preserving the
|
|
19
|
+
Liljegren-derived numerical files under their UChicago Argonne terms.
|
|
20
|
+
- Added the authoritative v1 ABI contract covering layouts, units, status and
|
|
21
|
+
ownership semantics, concurrency, symbols, and compatibility policy.
|
|
22
|
+
- Added an installed C++ consumer that validates public-header compatibility,
|
|
23
|
+
structure sizes and offsets, and shared-library linkage.
|
|
24
|
+
|
|
25
|
+
## v0.2.0 — 2026-08-18
|
|
26
|
+
|
|
27
|
+
- Added the fixed-layout `lwbgt_input_v1` and `lwbgt_output_v1` structures and
|
|
28
|
+
serial `lwbgt_calc_batch_v1` FFI entry point without changing the scalar ABI.
|
|
29
|
+
- Added versioned shared-library builds with a three-symbol dynamic export
|
|
30
|
+
surface while retaining the existing static archive.
|
|
31
|
+
- Added dependency-light Python, R, and Julia examples and made them release
|
|
32
|
+
gates on Linux/GCC, macOS/Clang, and Windows/MinGW CI.
|
|
33
|
+
- Added relocatable CMake and `pkg-config` installation metadata.
|
|
34
|
+
- Verified the final static and shared artifacts on Linux/GCC,
|
|
35
|
+
macOS/AppleClang, and Windows/MinGW, including installed consumers and all
|
|
36
|
+
three language examples.
|
|
37
|
+
- Revalidated the position-independent static build at 1.249× overall median
|
|
38
|
+
throughput with exact compatibility and all release gates passing.
|
|
39
|
+
|
|
40
|
+
## v0.1.0 — 2026-08-18
|
|
41
|
+
|
|
42
|
+
The release gate passes with 1.316× median single-thread throughput on GCC
|
|
43
|
+
13.3.0 and 1.289× on GCC 16.2.0. All 454 compatibility cases remain
|
|
44
|
+
bit-identical and every benchmark cohort exceeds 1.25×.
|
|
45
|
+
|
|
46
|
+
- Pinned Liljegren WBGT v1.1 commit
|
|
47
|
+
`cd672a886880b67f3f27bdbf75038d8f7ff0bac2` and source blob
|
|
48
|
+
`7bc6e6ddd76a538d6454b27e9b252667846e6c9b`.
|
|
49
|
+
- Added static `liblwbgt.a` and the permanent `calc_wbgt`/`esat` compatibility
|
|
50
|
+
declarations in `lwbgt.h`.
|
|
51
|
+
- Skipped radiative work that was multiplied by zero in the psychrometric
|
|
52
|
+
wet-bulb solve.
|
|
53
|
+
- Reused rounded air viscosity in cylinder and sphere convective coefficients.
|
|
54
|
+
- Hoisted invariant atmospheric, surface, and solar radiation terms from the
|
|
55
|
+
iterative globe and natural wet-bulb solves after profiling identified both
|
|
56
|
+
solves as the remaining hot paths.
|
|
57
|
+
- Proved exact output equality with GCC 13.3.0 and GCC 16.2.0.
|
|
58
|
+
- Proved that all three existing HeatStressBench C adapters compile unchanged
|
|
59
|
+
and produce byte-identical generated, decomposition, NASA POWER sample, and
|
|
60
|
+
ERA5 sample results when only the link input changes.
|
|
61
|
+
- Audited the static archive export surface and fixed the permanent supported
|
|
62
|
+
API at `calc_wbgt` and `esat`; inherited helper exports remain implementation
|
|
63
|
+
details.
|
lwbgt-0.3.0/CITATION.cff
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use lwbgt, please cite this software and the underlying Liljegren method."
|
|
3
|
+
title: "lwbgt"
|
|
4
|
+
type: software
|
|
5
|
+
abstract: "A stable low-level C/FFI computational kernel for Liljegren outdoor WBGT, derived from the Liljegren WBGT v1.1 C implementation."
|
|
6
|
+
authors:
|
|
7
|
+
- family-names: "Zheng"
|
|
8
|
+
given-names: "Yifei"
|
|
9
|
+
orcid: "https://orcid.org/0009-0001-4858-2025"
|
|
10
|
+
version: 0.3.0
|
|
11
|
+
date-released: 2026-08-19
|
|
12
|
+
repository-code: "https://github.com/zyf0717/lwbgt"
|
|
13
|
+
url: "https://github.com/zyf0717/lwbgt"
|
|
14
|
+
license-url: "https://github.com/zyf0717/lwbgt/blob/main/LICENSING.md"
|
|
15
|
+
keywords:
|
|
16
|
+
- WBGT
|
|
17
|
+
- Liljegren
|
|
18
|
+
- heat stress
|
|
19
|
+
- C
|
|
20
|
+
- FFI
|
|
21
|
+
- Python
|
|
22
|
+
references:
|
|
23
|
+
- type: article
|
|
24
|
+
authors:
|
|
25
|
+
- family-names: "Liljegren"
|
|
26
|
+
given-names: "James C."
|
|
27
|
+
- family-names: "Carhart"
|
|
28
|
+
given-names: "Richard A."
|
|
29
|
+
- family-names: "Lawday"
|
|
30
|
+
given-names: "Philip"
|
|
31
|
+
- family-names: "Tschopp"
|
|
32
|
+
given-names: "Stephen"
|
|
33
|
+
- family-names: "Sharp"
|
|
34
|
+
given-names: "Robert"
|
|
35
|
+
title: "Modeling the Wet Bulb Globe Temperature Using Standard Meteorological Measurements"
|
|
36
|
+
journal: "Journal of Occupational and Environmental Hygiene"
|
|
37
|
+
year: 2008
|
|
38
|
+
volume: 5
|
|
39
|
+
issue: 10
|
|
40
|
+
start: 645
|
|
41
|
+
end: 655
|
|
42
|
+
doi: "10.1080/15459620802310770"
|