From 8658c7b6df328d1b14b09c2520e24c0ac8255b33 Mon Sep 17 00:00:00 2001 From: jbbjarnason Date: Tue, 8 Feb 2022 17:53:16 +0000 Subject: [PATCH 1/3] py/modmath: New function math gcd. Addition to Math Special. Greatest common divisor. Inputs are constrained to only integers. Implemented with variadic amount of arguments. Tests from CPython. Link: https://github.com/python/cpython/blob/main/Lib/test/test_math.py. --- py/modmath.c | 57 ++++++++++++++++++++++++++++++++- tests/float/math_fun_special.py | 54 +++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/py/modmath.c b/py/modmath.c index 8fc821c9d5911..c051f37b9eab1 100644 --- a/py/modmath.c +++ b/py/modmath.c @@ -199,7 +199,61 @@ MATH_FUN_1(erfc, erfc) MATH_FUN_1(gamma, tgamma) // lgamma(x): return the natural logarithm of the gamma function of x MATH_FUN_1(lgamma, lgamma) -#endif + +/* gcd(x, y): return the greatest common divisor + GCD Pseudocode + * gcd(x,y) + * if x < y; + * x, y = y, x + * + * while y != 0: + * x,y = y, x mod y + * return x +*/ +STATIC mp_obj_t gcd_func(mp_obj_t x, mp_obj_t y) { + mp_obj_t temp; + if (mp_binary_op(MP_BINARY_OP_LESS, x, y) == mp_const_true) { + temp = x; + x = y; + y = temp; + } + + mp_obj_t zero = mp_obj_new_int(0); + while (mp_binary_op(MP_BINARY_OP_NOT_EQUAL, y, zero) == mp_const_true) { + temp = y; + y = mp_binary_op(MP_BINARY_OP_MODULO, x, y); + x = temp; + } + return x; +} + +STATIC mp_obj_t gcd_preprocess_arg(mp_obj_t presumed_integer) { + if (!mp_obj_is_int(presumed_integer)) { + mp_raise_msg_varg(&mp_type_TypeError, + MP_ERROR_TEXT("can't convert %s to int"), mp_obj_get_type_str(presumed_integer)); + } + return mp_unary_op(MP_UNARY_OP_ABS, presumed_integer); +} + +STATIC mp_obj_t mp_math_gcd(size_t n_args, const mp_obj_t *args) { + mp_obj_t e = gcd_preprocess_arg(args[--n_args]); + mp_obj_t d = gcd_preprocess_arg(args[--n_args]); + + mp_obj_t ans = gcd_func(d, e); + if (n_args == 0) { + return ans; + } + + // gcd(a, gcd(b, gcd(c, gcd(d, e))))) + do { + mp_obj_t next_variable = gcd_preprocess_arg(args[--n_args]); + ans = gcd_func(next_variable, ans); + } while (n_args > 0); + return ans; +} +MP_DEFINE_CONST_FUN_OBJ_VAR(mp_math_gcd_obj, 2, mp_math_gcd); + +#endif // MICROPY_PY_MATH_SPECIAL_FUNCTIONS // TODO: fsum #if MICROPY_PY_MATH_ISCLOSE @@ -425,6 +479,7 @@ STATIC const mp_rom_map_elem_t mp_module_math_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_erfc), MP_ROM_PTR(&mp_math_erfc_obj) }, { MP_ROM_QSTR(MP_QSTR_gamma), MP_ROM_PTR(&mp_math_gamma_obj) }, { MP_ROM_QSTR(MP_QSTR_lgamma), MP_ROM_PTR(&mp_math_lgamma_obj) }, + { MP_ROM_QSTR(MP_QSTR_gcd), MP_ROM_PTR(&mp_math_gcd_obj) }, #endif }; diff --git a/tests/float/math_fun_special.py b/tests/float/math_fun_special.py index 614470c0f15dd..673bbc5015a2c 100644 --- a/tests/float/math_fun_special.py +++ b/tests/float/math_fun_special.py @@ -50,3 +50,57 @@ print("{:.4g}".format(function(value))) except ValueError as e: print(str(e)) + + +# Tests for gcd mostly duplicated from +# https://github.com/python/cpython/blob/main/Lib/test/test_math.py + + +def assertRaises(exception, func, *args): + try: + print(func(*args)) + assert False + except exception: + pass + + +print(gcd(0, 0)) +print(gcd(1, 0)) +print(gcd(-1, 0)) +print(gcd(0, 1)) +print(gcd(0, -1)) +print(gcd(7, 1)) +print(gcd(7, -1)) +print(gcd(-23, 15)) +print(gcd(120, 84)) +print(gcd(84, -120)) +print(gcd(1216342683557601535506311712, 436522681849110124616458784)) + +x = 434610456570399902378880679233098819019853229470286994367836600566 +y = 1064502245825115327754847244914921553977 +for c in (652560, 576559230871654959816130551884856912003141446781646602790216406874): + a = x * c + b = y * c + print(gcd(a, b)) + print(gcd(b, a)) + print(gcd(-a, b)) + print(gcd(b, -a)) + print(gcd(a, -b)) + print(gcd(-b, a)) + print(gcd(-a, -b)) + print(gcd(-b, -a)) + +# In MP minimum argument count is 2 +# self.assertEqual(gcd(), 0) +# self.assertEqual(gcd(120), 120) +# self.assertEqual(gcd(-120), 120) + +print(gcd(120, 84, 102)) +print(gcd(120, 1, 84)) +print(gcd(6, 30, 40, -60, 20, 40)) +print(gcd(12345678912345678912345678911561561658135153135135135, 123456)) + +assertRaises(TypeError, gcd, 120.0) +assertRaises(TypeError, gcd, 120.0, 84) +assertRaises(TypeError, gcd, 120, 84.0) +assertRaises(TypeError, gcd, 120, 1, 84.0) From 26f32fbe1ac91b488578a51c4fd61a18bd4fcdbe Mon Sep 17 00:00:00 2001 From: jbbjarnason Date: Tue, 15 Feb 2022 16:19:42 +0000 Subject: [PATCH 2/3] docs/library/math: Add new function math.gcd to docs. --- docs/differences/python_35.rst | 2 +- docs/differences/python_39.rst | 2 +- docs/library/math.rst | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/differences/python_35.rst b/docs/differences/python_35.rst index 06cfbfc03cfa1..de1241867ed5c 100644 --- a/docs/differences/python_35.rst +++ b/docs/differences/python_35.rst @@ -101,7 +101,7 @@ Changes to built-in modules: +-----------------------------------------------------------------------------------------------------------+---------------+ | A new function *isclose()* provides a way to test for approximate equality. | | +-----------------------------------------------------------------------------------------------------------+---------------+ - | A new *gcd()* function has been added. The *fractions.gcd()* function is now deprecated. | | + | A new *gcd()* function has been added. The *fractions.gcd()* function is now deprecated. | Completed | +-----------------------------------------------------------------------------------------------------------+---------------+ | `os `_ | +-----------------------------------------------------------------------------------------------------------+---------------+ diff --git a/docs/differences/python_39.rst b/docs/differences/python_39.rst index 6852dd635ea82..93e54a0eaf870 100644 --- a/docs/differences/python_39.rst +++ b/docs/differences/python_39.rst @@ -90,7 +90,7 @@ Changes to built-in modules: +---------------------------------------------------------------------------------------------------------------+---------------+ | `math` | +---------------------------------------------------------------------------------------------------------------+---------------+ - | Expanded the *math.gcd()* function to handle multiple arguments. Formerly, it only supported two arguments | | + | Expanded the *math.gcd()* function to handle multiple arguments. Formerly, it only supported two arguments | Completed | +---------------------------------------------------------------------------------------------------------------+---------------+ | Added *math.lcm()*: return the least common multiple of specified arguments | | +---------------------------------------------------------------------------------------------------------------+---------------+ diff --git a/docs/library/math.rst b/docs/library/math.rst index a6f13d48c1892..3f9fbff3376da 100644 --- a/docs/library/math.rst +++ b/docs/library/math.rst @@ -104,6 +104,10 @@ Functions Return the gamma function of ``x``. +.. function:: gcd(x, y, ...) + + Return the greatest common divisor of any amount of numbers with minimum of 2 arguments. + .. function:: isfinite(x) Return ``True`` if ``x`` is finite. From a0bf6da4de2398cc858313918d3febc5eab260a3 Mon Sep 17 00:00:00 2001 From: jbbjarnason Date: Tue, 15 Feb 2022 21:44:09 +0000 Subject: [PATCH 3/3] .github/workflow/ports_unix: Update virtual env. to CPython 3.9. ports/windows/.appveyor: Update Windows virtual env. to 3.9. New Python features depend on more recent Python. --- .github/workflows/ports_qemu-arm.yml | 3 ++ .github/workflows/ports_unix.yml | 50 ++++++++++++++++++++++++++-- ports/windows/.appveyor.yml | 4 +-- tools/ci.sh | 6 +--- 4 files changed, 53 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ports_qemu-arm.yml b/.github/workflows/ports_qemu-arm.yml index 0489a93d5ad16..567559d78f94f 100644 --- a/.github/workflows/ports_qemu-arm.yml +++ b/.github/workflows/ports_qemu-arm.yml @@ -18,6 +18,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.9' - name: Install packages run: source tools/ci.sh && ci_qemu_arm_setup - name: Build and run test suite diff --git a/.github/workflows/ports_unix.yml b/.github/workflows/ports_unix.yml index dbd213cdff82f..39c6daaa50e27 100644 --- a/.github/workflows/ports_unix.yml +++ b/.github/workflows/ports_unix.yml @@ -41,6 +41,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.9' - name: Build run: source tools/ci.sh && ci_unix_standard_build - name: Run main test suite @@ -53,6 +56,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.9' - name: Build run: source tools/ci.sh && ci_unix_dev_build - name: Run main test suite @@ -65,8 +71,15 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Install packages - run: source tools/ci.sh && ci_unix_coverage_setup + - uses: actions/setup-python@v2 + with: + python-version: '3.9' + - name: Install python dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools pyelftools + - name: Print environment version + run: source tools/ci.sh && ci_unix_coverage_print_env - name: Build run: source tools/ci.sh && ci_unix_coverage_build - name: Run main test suite @@ -92,6 +105,13 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.9' + - name: Install python dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools pyelftools - name: Install packages run: source tools/ci.sh && ci_unix_32bit_setup - name: Build @@ -110,6 +130,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.9' - name: Install packages run: source tools/ci.sh && ci_unix_32bit_setup - name: Build @@ -124,6 +147,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.9' - name: Build run: source tools/ci.sh && ci_unix_float_build - name: Run main test suite @@ -136,6 +162,9 @@ jobs: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.9' - name: Install packages run: source tools/ci.sh && ci_unix_clang_setup - name: Build @@ -150,6 +179,9 @@ jobs: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.9' - name: Install packages run: source tools/ci.sh && ci_unix_clang_setup - name: Build @@ -164,6 +196,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.9' - name: Build run: source tools/ci.sh && ci_unix_settrace_build - name: Run main test suite @@ -176,6 +211,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.9' - name: Build run: source tools/ci.sh && ci_unix_settrace_stackless_build - name: Run main test suite @@ -190,7 +228,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 with: - python-version: '3.8' + python-version: '3.9' - name: Build run: source tools/ci.sh && ci_unix_macos_build - name: Run tests @@ -203,6 +241,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.9' - name: Install packages run: source tools/ci.sh && ci_unix_qemu_mips_setup - name: Build @@ -217,6 +258,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.9' - name: Install packages run: source tools/ci.sh && ci_unix_qemu_arm_setup - name: Build diff --git a/ports/windows/.appveyor.yml b/ports/windows/.appveyor.yml index d7192236dfbd4..5b383b1c739fd 100644 --- a/ports/windows/.appveyor.yml +++ b/ports/windows/.appveyor.yml @@ -1,10 +1,10 @@ -image: Visual Studio 2017 +image: Visual Studio 2019 clone_depth: 1 skip_tags: true environment: # Python version used - MICROPY_CPYTHON3: c:/python38/python.exe + MICROPY_CPYTHON3: c:/python39/python.exe # The variants. matrix: - PyVariant: dev diff --git a/tools/ci.sh b/tools/ci.sh index 5aed8a7dff1a6..2c0c5a82e8a0a 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -434,9 +434,7 @@ function ci_unix_dev_run_tests { ci_unix_run_tests_helper VARIANT=dev } -function ci_unix_coverage_setup { - sudo pip3 install setuptools - sudo pip3 install pyelftools +function ci_unix_coverage_print_env { gcc --version python3 --version } @@ -459,8 +457,6 @@ function ci_unix_32bit_setup { sudo dpkg --add-architecture i386 sudo apt-get update sudo apt-get install gcc-multilib g++-multilib libffi-dev:i386 - sudo pip3 install setuptools - sudo pip3 install pyelftools gcc --version python2 --version python3 --version pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy