Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b398b09

Browse files
committedMar 5, 2022
Provide Python bindings for Minpack
1 parent d5dbbaf commit b398b09

20 files changed

+1755
-13
lines changed
 

Diff for: ‎.github/workflows/CI.yml

+150-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ jobs:
2424
with:
2525
submodules: recursive
2626

27+
- name: Cache GFortran install
28+
if: ${{ contains(matrix.os, 'windows') }}
29+
id: cache
30+
uses: actions/cache@v2
31+
with:
32+
path: ./mingw-w64
33+
key: gcc-${{ matrix.gcc }}-${{ matrix.os }}
34+
2735
- name: Install GFortran (MacOS)
2836
if: ${{ contains(matrix.os, 'macos') }}
2937
run: |
@@ -40,7 +48,7 @@ jobs:
4048
--slave /usr/bin/gcov gcov /usr/bin/gcov-${{ matrix.gcc }}
4149
4250
- name: Install GFortran (Windows)
43-
if: ${{ contains(matrix.os, 'windows') }}
51+
if: ${{ contains(matrix.os, 'windows') && steps.cache.outputs.cache-hit != 'true' }}
4452
run: |
4553
Invoke-WebRequest -Uri ${{ env.DOWNLOAD }} -OutFile mingw-w64.zip
4654
Expand-Archive mingw-w64.zip
@@ -70,6 +78,7 @@ jobs:
7078
if: ${{ matrix.build == 'meson' }}
7179
run: >-
7280
meson setup _build
81+
--libdir=lib
7382
--prefix=${{ contains(matrix.os, 'windows') && '$pwd\_dist' || '$PWD/_dist' }}
7483
7584
- name: Compile project (meson)
@@ -84,6 +93,146 @@ jobs:
8493
if: ${{ matrix.build == 'meson' }}
8594
run: meson install -C _build --no-rebuild
8695

96+
- name: Create package (Unix)
97+
if: ${{ matrix.build == 'meson' && ! contains(matrix.os, 'windows') }}
98+
run: |
99+
tar cvf ${{ env.OUTPUT }} _dist
100+
xz -T0 ${{ env.OUTPUT }}
101+
echo "MINPACK_OUTPUT=${{ env.OUTPUT }}.xz" >> $GITHUB_ENV
102+
env:
103+
OUTPUT: minpack-${{ matrix.os }}.tar
104+
105+
- name: Create package (Windows)
106+
if: ${{ matrix.build == 'meson' && contains(matrix.os, 'windows') }}
107+
run: |
108+
tar cvf ${{ env.OUTPUT }} _dist
109+
xz -T0 ${{ env.OUTPUT }}
110+
echo "MINPACK_OUTPUT=${{ env.OUTPUT }}.xz" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
111+
env:
112+
OUTPUT: minpack-${{ matrix.os }}.tar
113+
114+
- name: Upload package
115+
if: ${{ matrix.build == 'meson' }}
116+
uses: actions/upload-artifact@v2
117+
with:
118+
name: ${{ env.MINPACK_OUTPUT }}
119+
path: ${{ env.MINPACK_OUTPUT }}
120+
121+
122+
Python:
123+
needs:
124+
- Build
125+
runs-on: ${{ matrix.os }}
126+
defaults:
127+
run:
128+
shell: ${{ contains(matrix.os, 'windows') && 'powershell' || 'bash -l {0}' }}
129+
strategy:
130+
fail-fast: false
131+
matrix:
132+
build: [meson]
133+
os: [ubuntu-latest, macos-latest]
134+
gcc: [10]
135+
python: ['3.7', '3.8', '3.9']
136+
137+
# Additional test for setuptools build
138+
include:
139+
- build: setuptools
140+
os: ubuntu-latest
141+
gcc: 10
142+
python: '3.9'
143+
144+
env:
145+
FC: gfortran
146+
CC: gcc
147+
MINPACK_OUTPUT: minpack-${{ matrix.os }}.tar.xz
148+
149+
steps:
150+
- name: Checkout code
151+
uses: actions/checkout@v2
152+
153+
- name: Cache GFortran install
154+
if: ${{ contains(matrix.os, 'windows') }}
155+
id: cache
156+
uses: actions/cache@v2
157+
with:
158+
path: ./mingw-w64
159+
key: gcc-${{ matrix.gcc }}-${{ matrix.os }}
160+
161+
- name: Install dependencies
162+
uses: mamba-org/provision-with-micromamba@main
163+
with:
164+
environment-file: config/ci/python-env.yaml
165+
extra-specs: |
166+
python=${{ matrix.python }}
167+
168+
- name: Install GFortran (MacOS)
169+
if: ${{ contains(matrix.os, 'macos') }}
170+
run: |
171+
brew install gcc@${{ matrix.gcc }}
172+
ln -s /usr/local/bin/gfortran-${{ matrix.gcc }} /usr/local/bin/gfortran
173+
ln -s /usr/local/bin/gcc-${{ matrix.gcc }} /usr/local/bin/gcc
174+
175+
- name: Install GFortran (Linux)
176+
if: ${{ contains(matrix.os, 'ubuntu') }}
177+
run: |
178+
sudo update-alternatives \
179+
--install /usr/bin/gcc gcc /usr/bin/gcc-${{ matrix.gcc }} 100 \
180+
--slave /usr/bin/gfortran gfortran /usr/bin/gfortran-${{ matrix.gcc }} \
181+
--slave /usr/bin/gcov gcov /usr/bin/gcov-${{ matrix.gcc }}
182+
183+
- name: Install GFortran (Windows)
184+
if: ${{ contains(matrix.os, 'windows') && steps.cache.outputs.cache-hit != 'true' }}
185+
run: |
186+
Invoke-WebRequest -Uri ${{ env.DOWNLOAD }} -OutFile mingw-w64.zip
187+
Expand-Archive mingw-w64.zip
188+
echo "$pwd\mingw-w64\mingw64\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
189+
shell: pwsh
190+
env:
191+
DOWNLOAD: "https://github.com/brechtsanders/winlibs_mingw/releases/download/10.3.0-12.0.0-9.0.0-r2/winlibs-x86_64-posix-seh-gcc-10.3.0-mingw-w64-9.0.0-r2.zip"
192+
193+
- name: Download package
194+
uses: actions/download-artifact@v2
195+
with:
196+
name: ${{ env.MINPACK_OUTPUT }}
197+
198+
- name: Unpack package (Unix)
199+
if: ${{ ! contains(matrix.os, 'windows') }}
200+
run: |
201+
tar xvf ${{ env.MINPACK_OUTPUT }}
202+
echo "MINPACK_PREFIX=$PWD/_dist" >> $GITHUB_ENV
203+
204+
- name: Unpack package (Windows)
205+
if: ${{ contains(matrix.os, 'windows') }}
206+
run: |
207+
tar xvf ${{ env.MINPACK_OUTPUT }}
208+
echo "MINPACK_OUTPUT=${{ env.OUTPUT }}.xz" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
209+
210+
- name: Install Python extension module (pip)
211+
if: ${{ matrix.build == 'setuptools' }}
212+
run: pip3 install . -vv
213+
working-directory: python
214+
env:
215+
PKG_CONFIG_PATH: ${{ env.PKG_CONFIG_PATH }}:${{ env.MINPACK_PREFIX }}/lib/pkgconfig
216+
LD_RUNPATH_SEARCH_PATH: ${{ env.MINPACK_PREFIX }}/lib
217+
218+
- name: Install Python extension module (meson)
219+
if: ${{ matrix.build == 'meson' }}
220+
run: |
221+
set -ex
222+
meson setup _build --prefix=$CONDA_PREFIX --libdir=lib
223+
meson compile -C _build
224+
meson install -C _build
225+
working-directory: python
226+
env:
227+
PKG_CONFIG_PATH: ${{ env.PKG_CONFIG_PATH }}:${{ env.MINPACK_PREFIX }}/lib/pkgconfig
228+
229+
- name: Test Python API
230+
run: pytest --pyargs minpack --cov=minpack -vv
231+
env:
232+
LD_LIBRARY_PATH: ${{ env.LD_LIBRARY_PATH }}:${{ env.MINPACK_PREFIX }}/lib
233+
DYLD_LIBRARY_PATH: ${{ env.DYLD_LIBRARY_PATH }}:${{ env.MINPACK_PREFIX }}/lib
234+
235+
87236
Docs:
88237
runs-on: ubuntu-latest
89238
defaults:

Diff for: ‎config/ci/python-env.yaml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: python
2+
channels:
3+
- conda-forge
4+
dependencies:
5+
- python
6+
- pip
7+
- pkgconfig
8+
- pytest
9+
- pytest-cov
10+
- coverage
11+
- cffi
12+
- numpy
13+
- meson
14+
- ninja

Diff for: ‎include/minpack.h

+58
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ typedef void (*minpack_func)(
1919
int* /* iflag */,
2020
void* /* udata */);
2121

22+
#ifdef MINPACK_CFFI
23+
extern "Python" void MINPACK_CALL
24+
func(
25+
int /* n */,
26+
const double* /* x */,
27+
double* /* fvec */,
28+
int* /* iflag */,
29+
void* /* udata */);
30+
#endif
31+
2232
/*
2333
* the purpose of hybrd is to find a zero of a system of
2434
* n nonlinear functions in n variables by a modification
@@ -84,6 +94,18 @@ typedef void (*minpack_fcn_hybrj)(
8494
int* /* iflag */,
8595
void* /* udata */);
8696

97+
#ifdef MINPACK_CFFI
98+
extern "Python" void MINPACK_CALL
99+
fcn_hybrj(
100+
int /* n */,
101+
const double* /* x */,
102+
double* /* fvec */,
103+
double* /* fjac */,
104+
int /* ldfjac */,
105+
int* /* iflag */,
106+
void* /* udata */);
107+
#endif
108+
87109
/*
88110
* the purpose of hybrj is to find a zero of a system of
89111
* n nonlinear functions in n variables by a modification
@@ -148,6 +170,19 @@ typedef void (*minpack_fcn_lmder)(
148170
int* /* iflag */,
149171
void* /* udata */);
150172

173+
#ifdef MINPACK_CFFI
174+
extern "Python" void MINPACK_CALL
175+
fcn_lmder(
176+
int /* m */,
177+
int /* n */,
178+
const double* /* x */,
179+
double* /* fvec */,
180+
double* /* fjac */,
181+
int /* ldfjac */,
182+
int* /* iflag */,
183+
void* /* udata */);
184+
#endif
185+
151186
/*
152187
* the purpose of lmder is to minimize the sum of the squares of
153188
* m nonlinear functions in n variables by a modification of
@@ -213,6 +248,17 @@ typedef void (*minpack_func2)(
213248
int* /* iflag */,
214249
void* /* udata */);
215250

251+
#ifdef MINPACK_CFFI
252+
extern "Python" void MINPACK_CALL
253+
func2(
254+
int /* m */,
255+
int /* n */,
256+
const double* /* x */,
257+
double* /* fvec */,
258+
int* /* iflag */,
259+
void* /* udata */);
260+
#endif
261+
216262
/*
217263
* the purpose of lmdif is to minimize the sum of the squares of
218264
* m nonlinear functions in n variables by a modification of
@@ -279,6 +325,18 @@ typedef void (*minpack_fcn_lmstr)(
279325
int* /* iflag */,
280326
void* /* udata */);
281327

328+
#ifdef MINPACK_CFFI
329+
extern "Python" void MINPACK_CALL
330+
fcn_lmstr(
331+
int /* m */,
332+
int /* n */,
333+
const double* /* x */,
334+
double* /* fvec */,
335+
double* /* fjrow */,
336+
int* /* iflag */,
337+
void* /* udata */);
338+
#endif
339+
282340
/*
283341
* the purpose of lmstr is to minimize the sum of the squares of
284342
* m nonlinear functions in n variables by a modification of

Diff for: ‎meson.build

+5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ project(
88
'buildtype=debugoptimized',
99
],
1010
)
11+
has_cc = add_languages('c', required: get_option('python'), native: false)
1112

1213
minpack_lib = library(
1314
meson.project_name(),
@@ -59,3 +60,7 @@ subdir('examples')
5960

6061
# add the testsuite
6162
subdir('test')
63+
64+
if get_option('python')
65+
subdir('python/minpack')
66+
endif

Diff for: ‎meson_options.txt

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
option(
2+
'python',
3+
type: 'boolean',
4+
value: false,
5+
description: 'Build Python extension module',
6+
)
7+
option(
8+
'python_version',
9+
type: 'string',
10+
value: 'python3',
11+
description: 'Python version to link against.',
12+
)

0 commit comments

Comments
 (0)
Please sign in to comment.