Skip to content

Commit

Permalink
Provide Python bindings for Minpack
Browse files Browse the repository at this point in the history
  • Loading branch information
awvwgk committed Mar 5, 2022
1 parent d5dbbaf commit aca4395
Show file tree
Hide file tree
Showing 18 changed files with 1,309 additions and 12 deletions.
151 changes: 150 additions & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ jobs:
with:
submodules: recursive

- name: Cache GFortran install
if: ${{ contains(matrix.os, 'windows') }}
id: cache
uses: actions/cache@v2
with:
path: ./mingw-w64
key: gcc-${{ matrix.gcc }}-${{ matrix.os }}

- name: Install GFortran (MacOS)
if: ${{ contains(matrix.os, 'macos') }}
run: |
Expand All @@ -40,7 +48,7 @@ jobs:
--slave /usr/bin/gcov gcov /usr/bin/gcov-${{ matrix.gcc }}
- name: Install GFortran (Windows)
if: ${{ contains(matrix.os, 'windows') }}
if: ${{ contains(matrix.os, 'windows') && steps.cache.outputs.cache-hit != 'true' }}
run: |
Invoke-WebRequest -Uri ${{ env.DOWNLOAD }} -OutFile mingw-w64.zip
Expand-Archive mingw-w64.zip
Expand Down Expand Up @@ -70,6 +78,7 @@ jobs:
if: ${{ matrix.build == 'meson' }}
run: >-
meson setup _build
--libdir=lib
--prefix=${{ contains(matrix.os, 'windows') && '$pwd\_dist' || '$PWD/_dist' }}
- name: Compile project (meson)
Expand All @@ -84,6 +93,146 @@ jobs:
if: ${{ matrix.build == 'meson' }}
run: meson install -C _build --no-rebuild

- name: Create package (Unix)
if: ${{ matrix.build == 'meson' && ! contains(matrix.os, 'windows') }}
run: |
tar cvf ${{ env.OUTPUT }} _dist
xz -T0 ${{ env.OUTPUT }}
echo "MINPACK_OUTPUT=${{ env.OUTPUT }}.xz" >> $GITHUB_ENV
env:
OUTPUT: minpack-${{ matrix.os }}.tar

- name: Create package (Windows)
if: ${{ matrix.build == 'meson' && contains(matrix.os, 'windows') }}
run: |
tar cvf ${{ env.OUTPUT }} _dist
xz -T0 ${{ env.OUTPUT }}
echo "MINPACK_OUTPUT=${{ env.OUTPUT }}.xz" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
env:
OUTPUT: minpack-${{ matrix.os }}.tar

- name: Upload package
if: ${{ matrix.build == 'meson' }}
uses: actions/upload-artifact@v2
with:
name: ${{ env.MINPACK_OUTPUT }}
path: ${{ env.MINPACK_OUTPUT }}


Python:
needs:
- Build
runs-on: ${{ matrix.os }}
defaults:
run:
shell: ${{ contains(matrix.os, 'windows') && 'powershell' || 'bash -l {0}' }}
strategy:
fail-fast: false
matrix:
build: [meson]
os: [ubuntu-latest, macos-latest]
gcc: [10]
python: ['3.7', '3.8', '3.9']

# Additional test for setuptools build
include:
- build: setuptools
os: ubuntu-latest
gcc: 10
python: '3.9'

env:
FC: gfortran
CC: gcc
MINPACK_OUTPUT: minpack-${{ matrix.os }}.tar.xz

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Cache GFortran install
if: ${{ contains(matrix.os, 'windows') }}
id: cache
uses: actions/cache@v2
with:
path: ./mingw-w64
key: gcc-${{ matrix.gcc }}-${{ matrix.os }}

- name: Install dependencies
uses: mamba-org/provision-with-micromamba@main
with:
environment-file: config/ci/python-env.yaml
extra-specs: |
python=${{ matrix.python }}
- name: Install GFortran (MacOS)
if: ${{ contains(matrix.os, 'macos') }}
run: |
brew install gcc@${{ matrix.gcc }}
ln -s /usr/local/bin/gfortran-${{ matrix.gcc }} /usr/local/bin/gfortran
ln -s /usr/local/bin/gcc-${{ matrix.gcc }} /usr/local/bin/gcc
- name: Install GFortran (Linux)
if: ${{ contains(matrix.os, 'ubuntu') }}
run: |
sudo update-alternatives \
--install /usr/bin/gcc gcc /usr/bin/gcc-${{ matrix.gcc }} 100 \
--slave /usr/bin/gfortran gfortran /usr/bin/gfortran-${{ matrix.gcc }} \
--slave /usr/bin/gcov gcov /usr/bin/gcov-${{ matrix.gcc }}
- name: Install GFortran (Windows)
if: ${{ contains(matrix.os, 'windows') && steps.cache.outputs.cache-hit != 'true' }}
run: |
Invoke-WebRequest -Uri ${{ env.DOWNLOAD }} -OutFile mingw-w64.zip
Expand-Archive mingw-w64.zip
echo "$pwd\mingw-w64\mingw64\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
shell: pwsh
env:
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"

- name: Download package
uses: actions/download-artifact@v2
with:
name: ${{ env.MINPACK_OUTPUT }}

- name: Unpack package (Unix)
if: ${{ ! contains(matrix.os, 'windows') }}
run: |
tar xvf ${{ env.MINPACK_OUTPUT }}
echo "MINPACK_PREFIX=$PWD/_dist" >> $GITHUB_ENV
- name: Unpack package (Windows)
if: ${{ contains(matrix.os, 'windows') }}
run: |
tar xvf ${{ env.MINPACK_OUTPUT }}
echo "MINPACK_OUTPUT=${{ env.OUTPUT }}.xz" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: Install Python extension module (pip)
if: ${{ matrix.build == 'setuptools' }}
run: pip3 install . -vv
working-directory: python
env:
PKG_CONFIG_PATH: ${{ env.PKG_CONFIG_PATH }}:${{ env.MINPACK_PREFIX }}/lib/pkgconfig
LD_RUNPATH_SEARCH_PATH: ${{ env.MINPACK_PREFIX }}/lib

- name: Install Python extension module (meson)
if: ${{ matrix.build == 'meson' }}
run: |
set -ex
meson setup _build --prefix=$CONDA_PREFIX --libdir=lib
meson compile -C _build
meson install -C _build
working-directory: python
env:
PKG_CONFIG_PATH: ${{ env.PKG_CONFIG_PATH }}:${{ env.MINPACK_PREFIX }}/lib/pkgconfig

- name: Test Python API
run: pytest --pyargs minpack --cov=minpack -vv
env:
LD_LIBRARY_PATH: ${{ env.LD_LIBRARY_PATH }}:${{ env.MINPACK_PREFIX }}/lib
DYLD_LIBRARY_PATH: ${{ env.DYLD_LIBRARY_PATH }}:${{ env.MINPACK_PREFIX }}/lib


Docs:
runs-on: ubuntu-latest
defaults:
Expand Down
14 changes: 14 additions & 0 deletions config/ci/python-env.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: python
channels:
- conda-forge
dependencies:
- python
- pip
- pkgconfig
- pytest
- pytest-cov
- coverage
- cffi
- numpy
- meson
- ninja
58 changes: 58 additions & 0 deletions include/minpack.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ typedef void (*minpack_func)(
int* /* iflag */,
void* /* udata */);

#ifdef MINPACK_CFFI
extern "Python" void MINPACK_CALL
func(
int /* n */,
const double* /* x */,
double* /* fvec */,
int* /* iflag */,
void* /* udata */);
#endif

/*
* the purpose of hybrd is to find a zero of a system of
* n nonlinear functions in n variables by a modification
Expand Down Expand Up @@ -84,6 +94,18 @@ typedef void (*minpack_fcn_hybrj)(
int* /* iflag */,
void* /* udata */);

#ifdef MINPACK_CFFI
extern "Python" void MINPACK_CALL
fcn_hybrj(
int /* n */,
const double* /* x */,
double* /* fvec */,
double* /* fjac */,
int /* ldfjac */,
int* /* iflag */,
void* /* udata */);
#endif

/*
* the purpose of hybrj is to find a zero of a system of
* n nonlinear functions in n variables by a modification
Expand Down Expand Up @@ -148,6 +170,19 @@ typedef void (*minpack_fcn_lmder)(
int* /* iflag */,
void* /* udata */);

#ifdef MINPACK_CFFI
extern "Python" void MINPACK_CALL
fcn_lmder(
int /* m */,
int /* n */,
const double* /* x */,
double* /* fvec */,
double* /* fjac */,
int /* ldfjac */,
int* /* iflag */,
void* /* udata */);
#endif

/*
* the purpose of lmder is to minimize the sum of the squares of
* m nonlinear functions in n variables by a modification of
Expand Down Expand Up @@ -213,6 +248,17 @@ typedef void (*minpack_func2)(
int* /* iflag */,
void* /* udata */);

#ifdef MINPACK_CFFI
extern "Python" void MINPACK_CALL
func2(
int /* m */,
int /* n */,
const double* /* x */,
double* /* fvec */,
int* /* iflag */,
void* /* udata */);
#endif

/*
* the purpose of lmdif is to minimize the sum of the squares of
* m nonlinear functions in n variables by a modification of
Expand Down Expand Up @@ -279,6 +325,18 @@ typedef void (*minpack_fcn_lmstr)(
int* /* iflag */,
void* /* udata */);

#ifdef MINPACK_CFFI
extern "Python" void MINPACK_CALL
fcn_lmstr(
int /* m */,
int /* n */,
const double* /* x */,
double* /* fvec */,
double* /* fjrow */,
int* /* iflag */,
void* /* udata */);
#endif

/*
* the purpose of lmstr is to minimize the sum of the squares of
* m nonlinear functions in n variables by a modification of
Expand Down
5 changes: 5 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ project(
'buildtype=debugoptimized',
],
)
has_cc = add_languages('c', required: get_option('python'), native: false)

minpack_lib = library(
meson.project_name(),
Expand Down Expand Up @@ -59,3 +60,7 @@ subdir('examples')

# add the testsuite
subdir('test')

if get_option('python')
subdir('python/minpack')
endif
12 changes: 12 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
option(
'python',
type: 'boolean',
value: false,
description: 'Build Python extension module',
)
option(
'python_version',
type: 'string',
value: 'python3',
description: 'Python version to link against.',
)
Loading

0 comments on commit aca4395

Please sign in to comment.