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/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. 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/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) 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